在GNU/Linux机器上,如果想要做"实时"(亚毫秒时间关键)任务,你几乎总是必须经历修补内核的冗长,复杂且容易出错的过程以获得足够的支持[ 1] [2].
最大的问题是,许多实时任务最有用的系统没有基本的硬件要求甚至不允许这些补丁工作,即高分辨率定时器外设.或者如果他们这样做,则它是特定于硬件的,因此需要根据具体情况在补丁中具体实现.即使CPU /指令时钟速率足够快以提供所需的时间粒度然后一些,这也是如此.
所以,我的问题是,什么是最好的第二位方式/技巧,以尽可能接近上述实时目标?人们可以简单地在应用程序源代码中执行的操作,而无需深入了解底层硬件或太多"内核黑客".
提升流程优先级,为"关键"任务启动额外的线程,以及(在C中)使用nanosleep()的变体是迄今为止我提出的最佳答案/技巧.我希望能找到更多.
( sched_setscheduler2)和朋友允许您使用两种不同的软实时调度程序,SCHED_FIFO并且SCHED_RR。在这些调度程序下运行的进程的优先级高于常规进程。因此,只要您只有其中几个进程,并控制它们之间的优先级,您实际上可以获得相当不错的实时响应。
SCHED_FIFO和的区别SCHED_RR是:
对于“实时”调度程序,最多有 100 个不同的优先级(POSIX 仅需要 32 个不同的级别,因此应该使用sched_get_priority_min(2)和sched_get_priority_max(2)来获取实际数量。调度程序都通过抢占进程和线程来工作优先级较低;区别在于它们如何处理具有相同优先级的任务。
SCHED_FIFO是先进先出调度程序(因此得名)。这意味着首先进入运行队列的任务被允许运行,直到完成、自愿放弃其在运行队列上的空间或被更高优先级的任务抢占。
SCHED_RR是一个循环调度程序。这意味着具有相同优先级的任务只允许运行一定的时间段。如果在该时间片用完时该任务仍在运行,则该任务将被抢占,并且运行队列中的下一个任务(具有相同优先级)将被允许运行直至其时间片。与 一样SCHED_FIFO,较高优先级的任务会抢占较低优先级的任务,但是,当被较高优先级任务抢占的任务被允许再次运行时,则仅允许其运行其量程中剩余的时间。有关如何设置任务的时间量,请参阅sched_rr_get_interval(2)中的注释部分。
MRG
在非 RT 内核上很难保证亚毫秒级。我知道近年来发生了很多非常好的工作(例如大内核锁已经消失),但这仍然不足以保证它。
您可以从 CERN 和费米实验室那些友好的原子爱好者那里了解 Scientific Linux 。可以安装 MRG(请参阅我的链接),它为您提供了 PREEMPT_RT 补丁的预打包设置。
或者,如果您有钱,您可以购买 Redhat MRG。这是一个完全受支持的 Linux 发行版,内置了 PREEMPT-RT 补丁,因此可以消除容易出现问题的内核补丁。
事实是,Redhat 对此收费很高(每次安装每年 3000 美元)。我认为他们已经跌倒了,它的最大客户之一是高速交易投资者,他们仍然拥有大量的美元,因此不会注意到每年 3000 美元/盒的费用。
我是如何接触 MRG 的
我已经用 MRG 做了相当多的工作(使用上述两者),而且效果非常好。它用线程替换了现有内核中的中断服务例程来服务中断。这意味着您可以以高于 IRQ 线程的优先级运行软件!如果您想接近保证应用程序的亚毫秒级延迟,那么您就必须这样做。
MRG 的东西似乎逐渐转移到主线内核中,在我看来这是一件好事。也许有一天它会成为主线。
其他问题
现代 CPU 热管理确实是一个令人头疼的问题。我的一些系统在系统管理中断(由 BIOS,而不是操作系统)提供服务时会锁定 0.3 秒,只是因为 CPU 预热了一点。看到这个。因此,您必须警惕底层硬件的功能。一般来说,您必须开始担心放弃现代 PC 的管理冷却,而回到一直快速旋转的大风扇。