ntp导致其他线程卡顿原因总结

          这个是在项目开发中遇到的一个比较严重的问题,第一影响到主界面的播放卡顿,第二影响到我这边线程同样卡顿,按道理来说两个没有数据交互的线程应该没有任何影响,改为detach模式也没用,最后定位到居然是单独的ntp线程影响到这两个线程的运行了,最后跟踪下去是popen和fgets的影响。

       都知道调用system命令无法获取返回值,所以很多时候采用popen来获取,但是有一个问题popen+fgets获取返回值的时候,本身popen并不阻塞,而是通过fgets使其处于阻塞状态,所以当system命令执行以后需要很长时间fgets获取返回值的时候,这时候当前ntp 线程一直处于阻塞等待数据的到来(但是为啥会阻塞其他线程呢???网上google,百度搜了很多解释的都模凌两可),最后给出我解决的方式把。

       ntp部分代码如下:  

void* NtpDate::ntpSyncProc(void* args)
{

	TvsStateManager *tvs = (TvsStateManager *)args;
	if(tvs != NULL)
	{
		bool update = false;
		float offset = 0;
		std::string cmd = "ntpdate ";
		cmd.append(mServer);
	//	cmd.append(" &");

		while(1)
		{
			LogE("##### Start execute ntpdate to sync time,ntp server(%s).\n",mServer.c_str());
			//system(cmd.c_str());
			FILE *freport = popen(cmd.c_str(), "r");
			int fd = fileno(freport);
			int flags;
			flags = fcntl(fd, F_GETFL, 0);
			flags |= O_NONBLOCK;
			fcntl(fd, F_SETFL, flags);

			if (freport == NULL) {
				LogW("Failed to execute ntpdate.\n");
			}
			else {
				char echo[1024];
//				usleep(10 * 1000 * 1000);
				if(fgets(echo, sizeof(echo), freport) != NULL)
				{
					char *ntp = strstr(echo, "offset");
					if (ntp != NULL) {
						if (sscanf(ntp, "offset %f sec", &offset) == 1) {
							update = true;

							LogE("Adjust time offset %f second.\n", offset);

							tvs->sendMessage(new Message(TvsStateManager::NtpDateMsg, reinterpret_cast<int &>(offset)));
						}
					}

					if (update == false) {
						LogE("Sync time failed: %s\n", echo);
					}
				}
				pclose(freport);
			}
			usleep(mPeriod * 1000 * 1000);
		}
	}

	return NULL;
}
         popen怎么使用的不解释了,说出关键部分:1.首先是将fgets阻塞模式改为了非阻塞模式使用了fcntl()函数,但是测试的过程发现由于非阻塞模式fgets还未获得数据就已经抛弃了,所以加了usleep睡眠10 s来获取,因为ntp返回值获得测试时大概是6s左右,所以设置10s保证能100%获得,当然可以设置更大,因为调用popen就已经执行了system命令,所以对于校时并不影响。2.另外也可以采用select模式改为非阻塞模式,代码就不贴了。3.此外还可以采用“&”后台运行(网上说"&"其实已经是非阻塞模式了,具体对不对不是很清楚),反正采用以上三种方式都可以解决ntp线程卡顿原因,以上三种方式我都试过。

posted @ 2017-07-10 11:32  奔涌吧,后浪  阅读(30)  评论(0编辑  收藏  举报