我意识到sched_rt_period_us
并且sched_rt_runtime_us
是为了防止在 RT 任务失控的情况下冻结系统。但我想知道是否可以使用较小的值来sched_rt_period_us
确保任务顺利运行。
我有一项简单的工作,每次调用需要不超过一毫秒左右的 CPU 时间 - 例如,通过 GPIO 引脚驱动步进电机。不过,我希望能够持续达到每秒不少于 100 个周期。这不超过 CPU 时间的 10% - 扣除抢占和调度程序开销。
我读过“sched_rt_period_us 中的非常小的值可能会导致系统不稳定”1但没有说明什么数量级才是“非常小的值”。如果我设置sched_rt_period_us
为 10000 并及时返回控制 ( sched_yield()
),我能否可靠地相信程序调用之间的延迟不超过 0.01 秒?
底层CPU可能是850MHz ARM,除了上述控制之外还有许多其他任务,但它们都不是实时的,甚至不需要“感觉响应”,仍然与默认值sched_rt_period_us
和sched_rt_runtime_us
(1秒中的95%)不同,我不能允许 RT 任务一次休眠 0.05 秒。
答案1
这是个老问题了,我们来试试。据我了解,您正在使用防死锁机制(这)以避免由于 RT 进程而导致正常进程饥饿。
你这么说
我有一个简单的工作,每次调用需要不超过一毫秒左右的 CPU 时间
是不是一个短周期任务或者由外部输入启动的简短任务?
对于第一种情况(短期任务): 你必须知道在Linux中内核3.14有可用的SCHED_DEADLINE
班级。这允许您为进程设置调度策略,以便它们定期拥有至少这么多的 CPU 时间。看看它的文档,您还可以在以下SCHED_DEADLINE
部分中找到一个易于理解的图表男人 7 安排。如果触发因素是外部的(随机的,非周期性的),那么它可能不是解决方案。
对于第二种情况(短暂的零星任务):如果您可以断言您的程序每次需要时只会做一小部分工作,那么您可以尝试停止使用优先级并只调用sched_yield当你的工作完成后。如果忙于池化,这是一种 ba 方法。如果你真的需要优先级那么也许你可以补充它睡眠,非 RT 进程将在 RT 进程休眠时运行。您可能还知道,如果它是由中断触发的,那么也许您应该使用下半部,更难的方法。
嗯,还有更多:您必须记住,可能会出现比您的实时进程更多的实时进程。例如,有内核线程。
答案2
与这个问题相关的东西并不多,但我确实找到了这个线程。它是 2009 年的版本,它是关于 2.6.X Linux 内核的,但看起来很合适。
这个话题的标题,主题:有关 sched-rt 组分配上限的问题:sched_rt_runtime_us - msg#01766。
摘抄
我写了一个小测试程序:
(a) 分叉两个线程,一个 SCHED_FIFO 和一个 SCHED_OTHER(该线程被重新分配为 -20),并将它们都绑定到特定的核心。
(b) 在紧密循环中运行两个线程(两个线程的迭代次数相同),直到 SCHED_FIFO 线程终止。
(c) 根据 SCHED_FIFO 线程的固定迭代次数计算常规 SCHED_OTHER 线程的已完成迭代次数。然后它会据此计算百分比。
我针对不同的 sched_rt_runtime_us 值(200 毫秒到 700 毫秒)运行上述工作负载,将 sched_rt_period_us 保持在 1000 毫秒不变。我还通过减小 sched_rt_period_us 的值(从而增加调度粒度)进行了一些实验,而行为没有明显变化。
我的观察结果以表格形式列出:
reg 线程已完成迭代次数 / sched_rt_runtime_us / RT 线程迭代次数的比率(以 % 为单位) sched_rt_runtime_us
- 0.2 100 %(常规线程完成其所有迭代)。
- 0.3 73%
- 0.4 45%
- 0.5 17%
- 0.6 0 %(SCHED_OTHER 线程完全受到限制。从未运行过)
- 0.7 0%