- 论坛徽章:
- 0
|
回复 TMBest
使用这个和使用usleep的效果差不多,达不到如3ms的间隔时间
hxh88888888 发表于 2010-05-28 18:15 ![]()
settimer和usleep的实现完全不同,settimer是让内核定期通过中断来通知的,每次中断时进程基本上就会被调度到,usleep是进程自己控制的,只有再被调度到并且时间够了之后才会被唤醒,所以usleep不准确,但settimer准确,我最近在项目中正好也用到settimer了,在我的项目中测试后是基本准确的,我的项目要求精确度是1ms。可以看一下我测试的一些经验:
因为项目的需要,需要精度为1ms的定时器,对于PC 机中的时间是由三种时钟硬件提供的,而这些时钟硬件又都基于固定频率的晶体振荡器来提供时钟方波信号输入。这三种时钟硬件是:实时时钟(Real Time Clock,RTC );可编程间隔定时器(Programmable Interval Timer ,PIT );时间戳计数器(Time Stamp Counter,TSC).在用户空间,windows下提供的API有:SetTImer,linux下提供的API有:rtc和settimer(也有其他的)。linux下的这两者都是通过中断来实现的,只是rtc是通过文件描述符来通知的,settimer是利用信号来通知的。
rtc基于文件描述符就意味着我们需要在单独的线程中编写一个死循环来检查文件描述符是否可读,然而线程调度的初始时间间隔是20ms,意味着只有等到线程被调度到时才可以测试文件描述符是否可读,这样的话就不准确了,达不到1ms的时间精度,还好经过测试事实不是这样的,用rtc的话可以基本精确到1ms。据我猜测是这样的:因为rtc本身也是通过中断来通知进程的,当进程被rtc通知时就尽量去调度正阻塞在rtc对应的文件描述符的那个线程,这样就不会因为线程调度时间间隔太长而导致rtc定时器不精确,经过实测,2个线程,64HZ的rtc通知58w次,仅有2次有问题,说明利用rtc做定时器是基本准确的,在项目中使用时也达到了较好的效果。
用settimer做定时器一样可以达到精确的效果,而且settimer是通过信号来通知的,意味着不需要另外开一个线程来做定时器,在当前线程即可做定时器。看起来应该是比rtc更好一些,但由于信号会中断低速系统调用,会导致其他部分的逻辑破坏,当然可以用SA_RESTART来保证低速系统调用被中断唤醒后会自动重启,但nanosleep不会(当然也有其他方法解决此问题),而我们项目中正好用到此系统调用,故而采用了rtc。
最终还是采用了settimer,因为在pc机上rtc只能让单进程使用,崩溃!经测试11.6w次,仅有一次为22ms,其余皆正常,可认为settimer比较准确,完全符合我的要求。 |
|