在我的应用程序中,有一个Linux线程需要每10毫秒激活一次,因此我使用ussleep(10*1000)。结果:线程从未在10毫秒后醒来,但总是在20毫秒后醒来。它与调度程序时间片,CONFIG_HZ等有关。我试图使用ussleep(1*1000)(即1毫秒),但结果是相同的。线程总是在20ms后被唤醒
但是在同一个应用程序中,另一个线程处理每10毫秒传入的网络事件(UDP数据包)。有阻塞'recvfrom'(或'select'),当有传入数据包时,它每10毫秒唤醒一次。为什么会这样呢?当没有数据包时,select是否必须将线程置于"睡眠"状态?为什么它的行为不同,我如何使我的线程每10毫秒活跃(或多或少)没有外部网络事件?
谢谢,Rafi
你似乎有一个普遍的印象,这些现代的抢占式多任务都是关于时间片和量子的。
他们不是。
它们都是关于软件和硬件中断的,定时器硬件中断只是许多可以设置线程就绪并改变运行线程集的中断之一。来自网卡的硬件中断导致网络驱动程序运行是另一个例子。
如果一个线程被阻塞,等待UDP数据报,并且数据报由于网卡中断运行驱动程序而变得可用,阻塞的线程将在NIC驱动程序运行后立即准备好,因为驱动程序将向线程发出信号并请求立即重新调度退出。如果您的机器没有超载高优先级的就绪线程,它将被设置为"立即"运行,以处理现在可用的数据报。这种机制提供了高性能的I/O,与任何计时器无关。
定时器中断定期运行以支持sleep()和其他系统调用超时。它运行在一个相当低的频率/高间隔,(如1/10ms),因为它是另一个应该最小化的开销。以更高的频率运行这样的中断将减少定时器粒度,代价是增加中断状态和重新调度开销,这在大多数桌面安装中是不合理的。
总结:你的定时器操作的粒度是10ms,但你的数据报I/O响应很快。
还有,为什么你的线程需要每10ms激活一次?你在投票支持什么?