【发布时间】:2015-05-20 07:51:12
【问题描述】:
我有一个在 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 等。但尽管如此,我还是想知道“香草”内核上以下时序异常背后的原因:
- 大约 0.03% 的所有
select()调用的时间超过 10 毫秒(请记住,超时时间为 8 毫秒)。 - 三个最差情况(超过 1200 万次调用)分别为 31.7 毫秒、46.8 毫秒和 64.4 毫秒。
- 上述所有事件都在 20 秒内发生,我认为某些 cron 作业可能受到干扰(尽管系统日志中的信息很少,除了当时正在执行
cron.daily的事实)。
所以,我的问题是:在这种极端情况下可能涉及哪些因素?这是否只是 Linux 内核本身可能发生的事情,即我是否必须切换到 RT_PREEMPT,甚至是非 USB 接口和 Xenomai,以获得更可靠的保证? /proc/sys/kernel/sched_rt_runtime_us会咬我吗?还有其他我可能遗漏的因素吗?
提出这个问题的另一种方式是,我还能做些什么来减少这些延迟异常而不切换到“更难”的实时环境?
更新:我观察到大约 118.4 毫秒的新“最坏情况”(一次超过 2500 万次 select() 调用)。即使我没有使用具有任何实时扩展功能的内核,我也有点担心,因为很明显可能会错过最后期限超过十分之一秒。
【问题讨论】:
-
我不是 linux 专家,但也许一个不可抢占的驱动程序中断有一个极端情况需要太多时间?那将是一个驱动程序错误。此外,您的延迟值奇怪地接近 16 毫秒的倍数。我敢打赌,你有很多持续 16 毫秒的电话。也许这是通信失败的连锁重试的症状,或者至少,某些事情失败并被重试。
-
16ms 倍数的“奇怪接近”只是这个例子的随机效应,我也观察过其他时间。
-
这是一个无滴答内核,还是你的 HZ 是多少?我记得前段时间
select()的粒度只有 10ms,HZ=100。请改用epoll。 -
在有问题的系统上,
CONFIG_HZ=250。但即使粒度是 10 毫秒,我也希望最多 20 毫秒而不是 8 毫秒,而不是 118 毫秒。 -
从我读到的关于
epoll的内容来看,只有在轮询大量文件描述符(例如stackoverflow.com/questions/8251717/…)时它才会提供优势。我只有一个。您能否指出其他支持epoll的原因,或者理想情况下为什么epoll在我观察到的最坏情况下可能做得更好的原因?将不胜感激。