第1章:固定优先级调度(FPS)与速率单调调度(RMS)算法原理
各位同学,咱们今天聊聊实时系统里最经典的一个调度算法——速率单调调度(RMS)。说实话,我做了十几年嵌入式系统,RMS 是我最早接触的调度算法之一。那时候刚入行,带我的老工程师就说:「小子,先把 RMS 搞明白,后面的事就好办了。」现在回想起来,这话一点不假。
1.1 什么是固定优先级调度?
固定优先级调度(FPS),说白了就是每个任务在系统启动时就定好了优先级,运行过程中谁也不许改。你想想看,这就像公司里的职级——你是 P7 就永远是 P7,不会因为今天活干得多就变成 P8。
在 FPS 里,优先级怎么定呢?最常见的方式就是按周期来。周期越短的任务,优先级越高。这就是 RMS 的核心思想。
核心要点:RMS 是一种静态优先级调度算法,任务的优先级与它的周期成反比——周期越短,优先级越高。
1.2 速率单调调度(RMS)算法原理
RMS 的全称是 Rate Monotonic Scheduling。这里的「速率」指的是任务释放的频率。你想想看,一个每 10ms 执行一次的任务,它的释放速率就是 100Hz;另一个每 100ms 执行一次的任务,速率就是 10Hz。RMS 的做法很简单:速率高的任务,优先级就高。
我举个例子你就明白了:
任务 T1:周期 10ms,执行时间 3ms
任务 T2:周期 20ms,执行时间 5ms
任务 T3:周期 50ms,执行时间 8ms
按照 RMS:
T1 的周期最短 → 优先级最高
T2 的周期次之 → 优先级中等
T3 的周期最长 → 优先级最低
嗯,这里要注意一点:RMS 假设所有任务都是周期性的,而且任务之间没有依赖关系。我在实际项目中遇到过有人把非周期任务硬塞进 RMS 框架里,结果调度一塌糊涂。千万别这么干。
1.3 RMS 的可调度性分析(Liu & Layland 定理)
好,现在问题来了:你按照 RMS 分配了优先级,怎么知道这些任务能不能在规定时间内跑完?这就引出了 Liu & Layland 定理。
1973 年,Liu 和 Layland 两位大神提出了一个充分条件(注意,是充分条件,不是充要条件):
Liu & Layland 定理:对于 n 个独立的周期性任务,如果所有任务的 CPU 利用率满足以下条件,则这些任务在 RMS 调度下是可调度的:
U ≤ n(2^(1/n) - 1)
这个公式看着有点吓人,我帮你算几个值:
| 任务数量 n | 利用率上界 U_max |
|---|---|
| 1 | 1.000 |
| 2 | 0.828 |
| 3 | 0.779 |
| 4 | 0.756 |
| 5 | 0.743 |
| ∞ | ln 2 ≈ 0.693 |
看到了吗?当任务数量趋于无穷时,利用率上界收敛到约 69.3%。也就是说,如果你的 CPU 利用率超过了 69.3%,RMS 就不能保证所有任务都能按时完成。
我的经验:在实际项目中,我一般会把 CPU 利用率控制在 60% 以下。为什么?因为 Liu & Layland 定理只是一个充分条件,不是必要条件。利用率在 69.3% 以下只是「保证」可调度,但实际系统中还有中断、上下文切换开销等因素。留点余量,心里踏实。
1.4 RMS 的优缺点
做了这么多年嵌入式,我对 RMS 的感情很复杂。它简单好用,但也不是万能的。咱们客观地聊聊它的优缺点。
优点
- 实现简单:优先级在编译时就定好了,运行时不需要动态调整。我记得第一次在 uC/OS-II 上实现 RMS,只改了几行代码就搞定了。
- 可预测性强:只要通过了可调度性分析,系统行为就是确定的。这对安全关键系统来说太重要了。
- 理论成熟:Liu & Layland 定理给了我们一个清晰的判断标准。不像某些调度算法,调不调得通全靠运气。
- 资源开销小:不需要像 EDF 那样维护动态优先级队列,对 CPU 和内存的消耗都很低。
缺点
- CPU 利用率受限:刚才说了,理论上限只有 69.3%。实际项目中能用到 50%-60% 就不错了。
- 对非周期任务不友好:RMS 天生是为周期性任务设计的。非周期任务怎么处理?我一般会把它转成周期任务,或者用服务器机制来处理。
- 优先级反转问题:这个我后面会专门讲。简单说就是低优先级任务占着资源不放,高优先级任务干等着。我曾经在一个无人机项目里被这个问题坑惨了。
- 任务周期必须已知:如果任务的周期不确定,RMS 就没法用了。
避坑指南:我曾经在一个项目中,把中断处理函数也当作 RMS 任务来调度。结果发现中断的优先级比所有任务都高,导致 RMS 的优先级分配完全失效。记住:RMS 只适用于任务级别的调度,中断是另一回事。
1.5 小结
RMS 是实时系统调度领域的基石。它简单、可靠、理论扎实。虽然有一些局限性,但在很多实际场景中依然是最优选择。我个人习惯在项目初期先用 RMS 搭一个原型,如果发现利用率不够或者有特殊需求,再考虑换成其他调度算法。
下一章咱们聊聊 RMS 在实际工程中的应用,以及怎么处理那些「不听话」的非周期任务。到时候我会分享一个我在工业控制项目中踩过的坑,保证让你印象深刻。