在非实时操作系统/内核上接近实时任务的最佳方法是什么?

时间:2013-03-19 17:02:20

标签: c linux real-time

在GNU / Linux机器上,如果想要做“实时”(亚毫秒时间关键)任务,你几乎总是必须经历修补内核的冗长,复杂且容易出错的过程足够的支持[1] [2]

最大的问题是,许多实时任务最有用的系统没有基本的硬件要求甚至不允许这些补丁工作,即高分辨率计时器外设。或者如果他们这样做,则它是特定于硬件的,因此需要根据具体情况在补丁中具体实现。即使CPU /指令时钟速率足够快以提供所需的时间粒度然后一些,也是如此。

所以,我的问题是,什么是最好的第二位方式/技巧,以尽可能接近上述实时目标?人们可以简单地在应用程序源代码中执行的操作,而无需深入了解底层硬件或太多“内核黑客”。

提升流程优先级,为“关键”任务启动额外的线程,以及(在C中)使用nanosleep()的变体是迄今为止我提出的最佳答案/技巧。我希望能找到更多。

4 个答案:

答案 0 :(得分:4)

sched_setscheduler(2)和朋友允许您使用两个不同的软实时调度程序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)中的Noes部分,了解如何设置任务的时间量。

答案 1 :(得分:3)

<强> MRG

在非RT内核上很难保证亚毫秒。我知道近年来已经发生了很多非常好的工作(例如,大内核锁已经消失了),但这还不足以保证它。

你可以从CERN和Fermilab的那些友好的原子生物学家那里获得科学Linux的look。可以安装MRG(参见我的链接),它为您提供了PREEMPT_RT补丁的预包装设置。

或者如果你有钱可以获得Redhat MRG。这是一个内置PREEMPT-RT补丁的完全支持的Linux发行版,因此可以解决内核修补问题。

事情是,Redhat为它收取批次(每年安装3000美元)。我认为他们已经下跌,其中一个最大的客户是高速交易的投资者,他们仍然需要多少批次,所以不会注意到3000美元/盒/年的出门。

我如何使用MRG

我已经使用MRG(使用上述两种方法)完成了相当多的工作,而且非常好。它用线程替换库存内核中的中断服务程序来服务中断。这意味着您可以以高于IRQ线程的优先级运行您的软件!如果您希望在应用程序上接近保证亚毫秒延迟,那么您就必须这样做。

似乎MRG事物逐渐漂移到主线内核中,这在我看来是件好事。也许有一天它会成为主线。

其他问题

现代CPU热管理可能是一个真正的痛苦。我有系统在系统管理中断服务时被锁定0.3秒(由流血的BIOS,而不是操作系统),只是因为CPU的温度升高了一点点。见this。因此,您必须警惕底层硬件的功能。一般来说,你必须开始担心放弃现代个人电脑的管理冷却,然后回到一个快速旋转的大风扇。

答案 2 :(得分:2)

通过从实时进程中删除其他进程的“干扰”,您可以在Linux上走得很远。我在Windows中使用了同样的东西,这是一个更大的恐怖,但它显示了方向。所以一种检查清单:

  • 最重要的(奇怪但真实):硬件。不要去买笔记本电脑,这将被优化为在SMM中断期间做一些奇怪的事情。你无能为力。
  • 驱动程序:Linux(和Windows)有糟糕的驱动程序和良好的驱动程序。与硬件有关。并且只有一种方法可以找到:基准测试。

与系统其他部分隔离,禁用所有共享:

  • 隔离一个CPU(man cpuset)。创建两个CPU集,一个用于正常流程,另一个用于实时流程。
  • 将代码的实时部分降至最低。与系统的其他部分的大缓冲区通信。将IO减少到最小值(因为IO有不好的保证)。
  • 使流程具有最高(软)实时优先级。
  • 禁用超线程(您不想共享)
  • 预先分配你需要的内存,以及mlock()内存。
  • 隔离您使用的设备。首先为设备分配专用IRQ(将其他设备移至另一个IRQ,或移除其他设备/驱动程序)。
  • 隔离您使用的IO。

减少系统其余部分的活动:

  • 只启动您真正需要的流程。
  • 删除您不需要的硬件,如磁盘和其他硬件。
  • 禁用交换。
  • 不要使用Linux内核模块或预先加载它们。模块的初始化是不可预测的。
  • 最好还删除用户:)

使其稳定且可重复:

  • 禁用所有节能。您希望始终保持相同的性能。
  • 查看所有BIOS设置,并从中删除所有“事件”和“共享”。因此,没有花哨的速度步骤,热管理等。选择低延迟,不要选择名称中带有'burst'的东西,因为这通常会影响吞吐量,从而降低性能。
  • 查看Linux驱动程序设置,并降低延迟(如果适用)。
  • 使用最近的内核,它每天尝试看起来像一个实时内核。

然后使用压力测试进行基准测试,并在记录最大值的同时将机器打开数天。的等待时间。

所以:祝你好运:)

答案 3 :(得分:1)

  

最大的问题是,许多实时任务最有用的系统没有基本的硬件要求甚至不允许这些补丁工作,即高分辨率计时器外设。

我强烈不同意:最大的问题是,您可能会在没有任何警告的情况下被阻止或抢占任意时间。如果您偶尔可以睡500分钟,那么如果您能以1us的准确度睡觉,这几乎无关紧要。实时计算是关于最坏情况的保证,而不是精确的睡眠间隔。如果您想对I2C EEPROM进行编程,您可以从高分辨率定时器中受益,该定时器可以让您尽可能地满足建立/保持时间,而不会浪费任何时间。偶尔的500ms的随机延迟并不重要,因为EEPROM只会坐在那里等待。但这不是一个实时应用程序。如果您正在实施一个带有1us更新的控制回路来驱动伺服,那么500ms的延迟将导致系统在系统不受控制地运行时发生巨大的位置中断。

您无法在应用程序中执行任何操作来解决磁盘驱动程序在中断上下文中花费数百毫秒处理IO完成的事实。使驱动程序对RT应用程序更友好的补丁是构成RT内核的补丁。