c - 什么可能会延迟我的 select() 调用?

标签 c linux real-time

我有一个在 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() 调用)。即使我没有使用带有任何实时扩展的内核,我还是有点担心最后期限显然会错过超过十分之一秒。

最佳答案

没有更多信息,很难指出具体的东西,所以我只是在这里猜测:

  1. 中断和由中断触发的代码在内核中占用大量时间,以至于您的实时线程明显延迟。这取决于中断的频率、涉及哪些中断处理程序等。
  2. 具有较低优先级的线程在放弃 cpu 或离开内核之前不会在内核中被中断。
  3. 正如 this SO answer 中指出的那样、CPU 系统管理中断和热管理也可能导致显着的时间延迟(海报观察到长达 300 毫秒)。

118 毫秒对于 1.6GHz CPU 来说似乎很多。但是一个意外锁定 cpu 一段时间的驱动程序就足够了。如果可以,请尝试禁用某些驱动程序或使用不同的驱动程序/硬件组合。

sched_rt_period_ussched_rt_period_us 如果它们设置为合理的值并且您的代码按您的预期运行,则它们应该不是问题。尽管如此,我还是会取消 RT 线程的限制,看看会发生什么。

你还能做什么?写一个设备驱动程序!这并不难,中断处理程序比实时线程获得更高的优先级。切换到实时内核而不是 YMMV 可能更容易。

关于c - 什么可能会延迟我的 select() 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30343466/

相关文章:

c - 当我尝试在函数中添加节点但在主函数中工作时,为什么我的程序崩溃了

c - 警告 : control reaches end of non-void function; error: null undeclared (c)

java - 无法通过 JDBC 连接到虚拟机上的 Oracle 11g : Connection reset

linux - grep 字符串在 n 行之前第一次出现,一旦与另一个字符串匹配

android - 如何在android中使用USB吉他接口(interface)实时处理音频?

firebase-realtime-database - 使用 Firebase 的两人象棋游戏

c - 如何从数字中提取某些位并将它们放入新变量中?

linux - 每日 grep 和输出 STATUS

c++ - 在 iOS 上创建实时房间后 Google Play 游戏服务崩溃

c - 在 C 中格式化非常大的数字