写线程循环调度时,总是需要获取系统时间戳来确定一次业务循环消耗长时间,我通常这样写:
unsigned int start_tick, used_tick;
while (!stop)
{
start_tick = get_sys_tick(); // 获取系统毫秒级时间戳
task_run(start_tick);
// 计算出一次任务轮循所用的时间,计算该休眠的时间
used_tick = get_sys_tick() - start_tick;
if (used_tick < 100)
ms_sleep(100 - used_tick);
}
// 获取系统毫秒时间戳
unsigned int get_sys_tick()
{
#ifdef _WIN32
//#include <sys/prctl.h>
return GetTickCount();
#else
//#include <sys/times.h>
return times(NULL);
#endif
}
// 跨平台sleep
void ms_sleep(unsigned int ms)
{
#ifdef _WIN32
//winsock.h
Sleep(ms);
#else
//unistd.h
usleep(ms * 1000);
#endif
}
task_run()函数将会100ms被调用一次,除非调用它花费100ms以上时间。task_run需要把时间传进去,这样如果里面的某项任务设置更低的循环频率,就可以用这个时间比较了。
需要注意的是,times(NULL)返回的时间,不是毫秒!需要乘10,精确度不足毫秒级。如果真要精确到毫秒,只能用gettimeofday() 了。
times这个函数比较神秘,有些博客说返回的是系统时钟数,需要除以sysconf(_SC_CLK_TCK)才能得到时间,但我写了小程序测试,返回的确实是墙上时间,目前我们平台都用这个函数获取linux毫秒时间戳,也没出什么问题。