我有一个在 Linux 上运行的小程序(在嵌入式 PC 上,双核 Intel Atom 1.6GHz,Debian 6 运行 Linux 2.6.32-5),它通过 FTDI USB 转串口转换器与外部硬件通信(使用 ftdi_sio
内核模块和 /dev/ttyUSB*
设备)。本质上,在我的主循环中运行
clock_gettime()
使用CLOCK_MONOTONIC
select()
超时为 8 毫秒clock_gettime()
和以前一样- 输出两次
clock_gettime()
调用的时间差
为了获得一定程度的“软”实时保证,此线程以最高优先级作为 SCHED_FIFO
运行(在 top
中显示为“RT”)。它是系统中唯一以此优先级运行的线程,没有其他进程具有这样的优先级。我的进程有另一个优先级较低的 SCHED_FIFO
线程,而其他所有线程都在 SCHED_OTHER
。这两个“实时”线程不受 CPU 限制,除了等待 I/O 和传递数据外几乎不做任何事情。
我使用的内核没有 RT_PREEMPT 补丁(我将来可能会切换到那个补丁)。我知道如果我想要“适当的”实时,我需要切换到 RT_PREEMPT 或更好的 Xenomai 或类似的。但尽管如此,我还是想知道“ Vanilla ”内核上以下时序异常背后的原因:
- 所有
select()
调用中大约有 0.03% 的时间超过 10 毫秒(请记住,超时为 8 毫秒)。 - 三个最差的情况(在超过 1200 万次调用中)分别为 31.7 毫秒、46.8 毫秒和 64.4 毫秒。
- 以上所有事件都在 20 秒内发生,我认为可能是某些 cron 作业造成了干扰(尽管系统日志中的信息很少,除了
cron.daily
是当时被处决)。
所以,我的问题是:在这种极端情况下可能涉及哪些因素?这是否只是 Linux 内核本身内部可能发生的事情,即我是否必须切换到 RT_PREEMPT,甚至是非 USB 接口(interface)和 Xenomai,以获得更可靠的保证? /proc/sys/kernel/sched_rt_runtime_us
会咬我吗?是否还有其他我可能遗漏的因素?
提出这个问题的另一种方式是,在不切换到“更难”的实时环境的情况下,我还能做些什么来减少这些延迟异常?
更新:我观察到一个新的“最坏的最坏情况”,大约 118.4 毫秒(曾经超过总共约 2500 万次 select()
调用)。即使我没有使用带有任何实时扩展的内核,我还是有点担心最后期限显然会错过超过十分之一秒。
最佳答案
没有更多信息,很难指出具体的东西,所以我只是在这里猜测:
- 中断和由中断触发的代码在内核中占用大量时间,以至于您的实时线程明显延迟。这取决于中断的频率、涉及哪些中断处理程序等。
- 具有较低优先级的线程在放弃 cpu 或离开内核之前不会在内核中被中断。
- 正如 this SO answer 中指出的那样、CPU 系统管理中断和热管理也可能导致显着的时间延迟(海报观察到长达 300 毫秒)。
118 毫秒对于 1.6GHz CPU 来说似乎很多。但是一个意外锁定 cpu 一段时间的驱动程序就足够了。如果可以,请尝试禁用某些驱动程序或使用不同的驱动程序/硬件组合。
sched_rt_period_us
和 sched_rt_period_us
如果它们设置为合理的值并且您的代码按您的预期运行,则它们应该不是问题。尽管如此,我还是会取消 RT 线程的限制,看看会发生什么。
你还能做什么?写一个设备驱动程序!这并不难,中断处理程序比实时线程获得更高的优先级。切换到实时内核而不是 YMMV 可能更容易。
关于c - 什么可能会延迟我的 select() 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30343466/