4. 速率单调调度(RMS):RMS原理、任务周期与优先级映射、RMS的可调度性分析
4.1 先聊聊RMS的直觉
速率单调调度,英文叫Rate Monotonic Scheduling,简称RMS。这名字听着挺唬人,其实说白了就一句话:任务周期越短,优先级越高。
我刚开始接触实时系统时,觉得这规则也太简单了吧?后来在一条包装生产线上,我亲眼看到有人把周期长的任务设成了高优先级,结果短周期任务一直被阻塞,电机控制直接抖成了筛子。嗯,从那以后我再也不敢小看RMS了。
RMS是静态优先级调度里最经典的算法。它不需要你动态计算什么截止时间,也不需要你维护什么就绪队列的排序。你只需要在系统设计阶段,把每个任务的优先级定死,后面就按这个跑。
你想想看,这多省心?
4.2 RMS的核心原理
RMS的原理其实就一条铁律:任务的优先级与它的周期成反比。周期越短,优先级越高。
为什么这么定?因为短周期任务通常意味着更高的实时要求。比如一个1ms的电流环控制,和一个100ms的通信任务,谁更紧急?当然是电流环。如果通信任务抢了电流环的CPU时间,电机可能直接就过流了。
我在一个六轴机器人项目中就吃过这个亏。当时我把轨迹规划(周期50ms)设成了最高优先级,结果电流环(周期1ms)被频繁打断,机器人手臂在高速度下直接抖出了共振。后来改成RMS规则,电流环优先级最高,问题立刻解决。
- 每个任务有一个固定的周期 Ti
- 每个任务有一个最坏情况执行时间 Ci
- 优先级 Pi 与 Ti 成反比
- 调度是抢占式的——高优先级任务可以打断低优先级任务
4.3 任务周期与优先级映射
优先级映射这件事,我习惯用一个简单的表格来梳理。假设我们有三个任务:
| 任务名称 | 周期 T (ms) | 执行时间 C (ms) | RMS优先级 |
|---|---|---|---|
| 电流环控制 | 1 | 0.2 | 最高(1) |
| 速度环控制 | 5 | 0.5 | 中(2) |
| 通信任务 | 100 | 2.0 | 最低(3) |
你看,周期最短的电流环优先级最高,周期最长的通信任务优先级最低。这个映射关系一旦确定,在系统运行期间就不会再变了。
实际项目中,我一般会留一个「空闲任务」作为最低优先级。这个任务跑一些非实时的工作,比如日志记录、状态上报。这样即使所有实时任务都闲着,CPU也不会空转。
4.4 RMS的可调度性分析
好,优先级定好了,任务也写完了。但你怎么知道这些任务一定能跑得过来?这就是可调度性分析要回答的问题。
RMS有一个经典的充分条件,叫刘-莱兰条件(Liu & Layland)。它说:对于n个周期任务,如果所有任务的CPU利用率满足下面这个公式,那么这些任务一定是可调度的:
U = Σ (C_i / T_i) ≤ n * (2^(1/n) - 1)
这个公式看着有点吓人,我刚开始学的时候也觉得头大。但实际用起来,我一般会先算一个利用率上限表:
| 任务数 n | 利用率上限 |
|---|---|
| 1 | 1.000 |
| 2 | 0.828 |
| 3 | 0.779 |
| 4 | 0.756 |
| 5 | 0.743 |
| →∞ | ln 2 ≈ 0.693 |
当任务数无限多时,利用率上限趋近于69.3%。也就是说,如果你把所有任务的CPU利用率加起来不超过69%,那RMS一定能调度得过来。
但注意,这只是充分条件,不是必要条件。也就是说,即使利用率超过了这个上限,系统仍然有可能是可调度的。我遇到过不少项目,利用率跑到85%依然稳定运行。但作为工程师,我建议你保守一点,给自己留点余量。
4.5 一个完整的可调度性验证例子
咱们拿刚才那个三任务的例子来算一下:
任务1:C1=0.2ms, T1=1ms → U1=0.2
任务2:C2=0.5ms, T2=5ms → U2=0.1
任务3:C3=2.0ms, T3=100ms → U3=0.02
总利用率 U = 0.2 + 0.1 + 0.02 = 0.32
n=3时,利用率上限 = 3 * (2^(1/3) - 1) ≈ 0.779
0.32 ≤ 0.779 → 可调度!
这个结果说明,这三个任务在RMS调度下是安全的。但我在实际项目中,还会额外做一步:响应时间分析。因为利用率条件只是充分条件,而响应时间分析能给出更精确的结论。
响应时间分析的核心思想是:计算每个任务在最坏情况下的完成时间,看它是否小于等于它的截止时间(在RMS中,截止时间通常等于周期)。这个计算稍微复杂一些,需要迭代求解,但很多RTOS工具链都支持自动计算。
4.6 RMS的局限性
RMS不是万能的。我遇到过几个场景,RMS就不太合适:
- 任务周期相差太大:比如一个1ms的任务和一个1000ms的任务,RMS会把1ms的任务优先级设得极高,但1000ms的任务可能永远得不到CPU时间——如果1ms任务一直占着CPU不放的话。不过这种情况在实际中很少见,因为短周期任务通常执行时间也很短。
- 任务有共享资源:如果高优先级任务和低优先级任务共享同一个互斥锁,就可能出现优先级反转。这时候需要配合优先级继承协议或优先级天花板协议来解决。
- 非周期任务:RMS只适用于周期任务。如果你的系统里有大量的事件驱动任务,那就要考虑其他调度算法了,比如EDF(最早截止时间优先)。
4.7 本章知识体系
下面这张图,是我自己总结的RMS知识体系。你可以把它当作一个快速参考:
这张图把RMS的核心内容分成了三块:优先级映射、可调度性分析、局限性。我个人习惯在做系统设计时,先按这个框架走一遍,确保没有遗漏。
好了,关于RMS的内容就讲到这里。记住一句话:周期越短,优先级越高。这个原则虽然简单,但能解决你80%的实时调度问题。剩下的20%,靠经验和分析工具来补。
- RMS是静态优先级调度,优先级与周期成反比
- 可调度性分析用刘-莱兰条件作为充分条件
- 实际项目中要留余量,Ci 取最坏情况
- 注意优先级反转问题,必要时使用优先级继承
公众号:蓝海资料掘金营,微信deep3321