这个问题不是关于在Windows(XP或更高版本)上准确地计时,而是关于通过回调或中断非常快速地做某事。
我需要每1毫秒,或者最好是每100微秒定期做一些事情。我需要做的是以这个速率驱动一些异步硬件(以太网)向网络输出稳定的数据包流,并使该数据流看起来尽可能规则和同步。但是如果这个问题可以从(以太网)设备中分离出来,知道一般的答案就好了。
在你说“甚至不要考虑使用Windows!!!!”,一点上下文。并非所有的实时系统都有相同的需求。大多数时候,歌曲和视频在Windows上播放是可以接受的,尽管平均每10- 16毫秒左右需要处理一块音频或图像。通过适当的缓冲,Windows可以有其可变的延迟,但硬件可以广泛地免疫它们,并保持稳定的同步事件流发生。即便如此,我们大多数人还是能容忍偶尔的小故障。我的应用程序就是这样-可能相当宽容。
对我来说,昂贵的选择是将我的整个应用程序移植到Linux。但是Linux只是在同一硬件上运行的不同软件,所以我强烈的偏好是编写一些更好的软件,并坚持使用Windows。我拥有能够消除所有竞争硬件和软件(没有互联网或其他网络访问,没有其他应用程序运行等)的奢侈。我有没有前景让Windows做到这一点?我会遇到哪些限制?
我知道我的目标硬件有一个高性能事件计时器,并且可以将此计时器编程为中断,但没有驱动程序。我能写一个吗?有没有有用的例子?我还没找到。这会干扰QueryPerformanceCounter吗?我将使用一个以太网设备,这是否意味着如果我明智地使用select(),一切都会变得简单?
欢迎指向有用文章的指针-我已经找到了几十个关于如何获得准确时间的概述,但还没有一个关于如何做这样的事情,除了使用相当于忙碌等待的东西。有没有办法避免忙碌的等待?是否有内核模式或设备驱动程序选项?
4条答案
按热度按时间qjp7pelc1#
您应该考虑查看多媒体计时器。这些是定时器,旨在解决您正在寻找的排序。
在MSDN上看一下。
hujrc8aj2#
我使用DirectX 9,使用
QueryPerformanceCounter
,但你需要占用至少一个核心,因为任务切换会让你混乱。为了更好地比较计时器,您可以查看
http://www.geisswerks.com/ryan/FAQS/timing.html
hpxqektj3#
如果您遇到计时器粒度问题,我建议使用带自旋循环的Sleep()。基本上,代码应该做如下事情:
这样,你将有一个高精度的睡眠,如果它们中的很多都大于调度粒度(假设10ms),这不会对你的CPU造成太大的负担。您可以在循环中发送数据包,同时使用高精度睡眠来计时。
音频在大多数系统上工作正常的原因是音频设备有自己的时钟。你只需将音频数据缓冲到它,它就会负责播放它,并在缓冲区为空时中断程序。事实上,如果回放引擎依赖于CPU时钟,则音频卡时钟和CPU时钟之间的时间偏差会导致问题。
编辑:你可以通过使用一个线程来做一个定时器抽象,这个线程使用一个锁保护的最小堆的定时条目(堆比较是在到期时间戳上完成的),然后你可以在PrecisionSleep()到下一个时间戳完成时使用callback()或SetEvent()。
cwxwcias4#
程序启动时使用NtSetTimerResolution设置计时器分辨率。是的,它是未记录的函数,但工作良好。您也可以使用NtQueryTimerResolution来了解计时器分辨率(在设置之前和设置新分辨率之后)。
您需要使用
GetProcAddress
从NTDLL.DLL
动态获取这些函数的地址,因为它没有在头文件或任何LIB文件中声明。以这种方式设置计时器分辨率会影响
Sleep
、Windows计时器、返回当前时间的函数等。