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

2023-06-14,,

这个是在项目开发中遇到的一个比较严重的问题,第一影响到主界面的播放卡顿,第二影响到我这边线程同样卡顿,按道理来说两个没有数据交互的线程应该没有任何影响,改为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线程卡顿原因,以上三种方式我都试过。

ntp导致其他线程卡顿原因总结的相关教程结束。

《ntp导致其他线程卡顿原因总结.doc》

下载本文的Word格式文档,以方便收藏与打印。