什么可以延迟我的select()调用?

min*_*iot 10 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以最高优先级运行(显示为"RT" top).它是系统中唯一以此优先级运行的线程,没有其他进程具有此类优先级.我的进程有另一个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接口和Xenomai,以获得更可靠的保证吗?可能/proc/sys/kernel/sched_rt_runtime_us咬我?还有其他因素我可能错过了吗?

提出这个问题的另一种方法是,如果切换到"更难"的实时环境,我还能做些什么来减少这些延迟异常?

更新:我观察到一个新的,"更糟糕的最坏情况",大约118.4毫秒(一次超过总共约2500万个select()电话).即使我没有使用任何实时扩展的内核,我有点担心的是,截止日期显然可能超过十分之一秒.

Mac*_*ser 2

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

  1. 中断和由中断触发的代码在内核中占用大量时间,导致实时线程显着延迟。这取决于中断的频率、涉及哪些中断处理程序等。
  2. 优先级较低的线程不会在内核内部被中断,直到它让出 cpu 或离开内核。
  3. 正如此 SO 答案中所指出的,CPU 系统管理中断和热管理也会导致显着的时间延迟(发布者观察到高达 300 毫秒)。

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

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

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