【问题标题】:What are the best ways to do close to real-time tasks on a non real-time OS/kernel?在非实时操作系统/内核上执行接近实时任务的最佳方法是什么?
【发布时间】:2013-03-08 12:08:43
【问题描述】:

在 GNU/Linux 机器上,如果想要执行“实时”(亚毫秒级时间关键)任务,您几乎总是必须经历冗长、复杂且容易出现问题的内核修补过程以暴露足够的支持[1][2].

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

所以,我的问题是,有哪些最佳的第二名方法/技巧可以尽可能接近上述实时目标?可以简单地在应用程序源代码中完成的事情,无需深入了解底层硬件或过多的“内核黑客”。

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

【问题讨论】:

    标签: c linux real-time


    【解决方案1】:

    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 部分,了解如何设置任务的时间段。

    【讨论】:

    • 谢谢,这很有用,事实上这是我建议的可能性之一。无论如何,您能否编辑您的答案以解释 SCHED_FIFO 和 SCHED_RR 之间的区别。我可以谷歌它,但你在你的答案中解释它可能会让你从我这里获得最佳答案。再次感谢。
    【解决方案2】:

    MRG

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

    您可以在科学 Linux 上从 CERN 和费米实验室那些友好的原子困扰者那里获得look。这可以安装 MRG(请参阅我的链接),它为您提供 PREEMPT_RT 补丁的预打包设置。

    或者,如果您有钱,您可以购买 Redhat MRG。这是一个完全支持的 Linux 发行版,内置了 PREEMPT-RT 补丁,因此可以消除容易出现问题的内核补丁。

    问题是,Redhat 收取 很多 费用(每次安装每年 3000 美元)。我认为他们已经跌倒了,它的最大客户之一是高速交易投资者,他们仍然有大量的资金,因此不会注意到每箱 3000 美元/年的价格。

    我是如何与 MRG 相处的

    我已经对 MRG 做了很多工作(使用上述两种方法),它非常好。它用服务中断的线程替换了普通内核中的中断服务例程。这意味着您可以以高于 IRQ 线程的优先级运行您的软件!如果您想要接近保证应用程序的亚毫秒级延迟,这就是您必须做的事情。

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

    其他陷阱

    现代 CPU 热管理可能会让人头疼。我的系统在处理系统管理中断时锁定了 0.3 秒(通过 bleedin' BIOS,而不是操作系统),只是因为 CPU 有点热身。见this。因此,您必须警惕底层硬件的功能。通常,您必须开始担心放弃现代 PC 的管理冷却,并重新使用一直快速旋转的大风扇。

    【讨论】:

    • 感谢您的回答,但您的建议似乎不是仅在应用程序源代码中就可以完成的。这并不意味着您的方法是错误的或不会在物理上起作用,只是它过于依赖特定的软件包并且不是一个技巧或技术。我一直在寻找一种更通用的修复程序,它可以应用于多种 Gnu/Linux。希望一些功能齐全的实时特性最终能进入官方 Linux 内核,就像你所说的 MRG 的一部分一样。但截至目前,情况似乎并非如此。
    【解决方案3】:

    通过消除从其他进程到实时进程的“干扰”,您可以在 Linux 上走得更远。我在 Windows 中玩过同样的事情,这是一个更大的恐惧,但它显示了方向。所以一种清单:

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

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

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

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

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

    使其稳定且可重现:

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

    然后进行基准测试,使用压力测试并让机器开启数天,同时记录最大值。延迟。

    所以:祝你好运:)

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

      • 感谢您的意见。但是你有点误会了。高分辨率定时器外设让补丁工作。补丁本身修复了最坏的情况,这就是它们的用途。但是,如果没有硬件,补丁就无法完成他们打算做的工作。因此,没有高分辨率计时器硬件直接导致无法修复最坏情况下的时序。
      猜你喜欢
      • 2014-04-10
      • 1970-01-01
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-07
      • 2011-06-19
      • 2018-05-16
      相关资源
      最近更新 更多