admin 管理员组文章数量: 887021
背景
在实际工作过程中,比如与硬件交互、媒体视频播放、性能分析以及多线程任务同步时,可能需要在windows平台下实现ms级别精度的定时器。然而,这种需求虽然存在,但是由于windows系统并不是一个实时操作系统,实现这种精度的定时器,并不是一件容易的事情。
Windows 不是实时操作系统,所以任何方案都无法绝对保证定时器的精度,只是能尽量减少误差。所以,系统的稳定性不能完全依赖于定时器,必须考虑失去同步时的处理。
等待策略
要想实现高精度定时器,必须需要等待和计时两种基础功能,等待用来跳过一定时间间隔,计时可以进行时间检查,用以调整等待事件。
等待策略实际就是两种:
1. 自旋等待:让CPU空转消耗时间,占用大量CPU时间,但是时间高度可控。
2. 阻塞等待:线程进入阻塞状态,让出CPU时间片,在等待一定时间后再由操作系统调度回到运行状态。阻塞时不占用CPU,然而需要操作系统调度,时间难以控制。
可以看到二者各有优劣,应该按照不同需求进行不同的实现。
所以难点在于等待策略,下面先分析简单的自旋等待。
自旋等待
伪代码如下:
等待开始时间=当前计时
while((当前计时-等待开始时间)<需要等待的时间)
{
自旋;
}
阻塞等待
阻塞等待会把控制权交给操作系统,这样就必须确保操作系统能够及时的将定时器线程调度回运行状态。默认情况下,Windows的系统定时器精度为15.625ms,也就是说时间切片是这个尺寸。如果线程阻塞,出让其时间片进行等待,再被调度运行的时间至少是一个切片15.625ms。那么必须减少时间切片的长度,才能实现更高的精度。
一般实现阻塞等待都用的是thread库的sleep函数,实测sleep函数的精度不高,估计也就ms级的,也就是可能会产生+1ms的误差。
sleep会出让剩余的cpu时间片给优先级相同的线程,而yield则是出让剩余的cpu时间片给运行在同一核心上的线程。在出让的时间片结束后,其会被重新调度。一般情况下,整个过程可以在1ms内完成。
另外,sleep或者yield在CPU高负载情况下非常不稳定,实测可能会阻塞高达几ms的时间,所以可能会产生更多的误差
版权声明:本文标题:针对windows系统的高精度定时器 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1729008899h1306352.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论