4. 速率单调调度(RMS):原理、优先级分配规则、可调度性判定、优缺点分析

好,咱们今天来聊聊RMS。全称是Rate Monotonic Scheduling,中文叫速率单调调度。

这玩意儿在硬实时系统里,地位相当高。我当年刚入行时,第一个接触的实时调度算法就是它。为什么?因为它简单、直观,而且有严格的理论支撑。说白了,它是最经典的固定优先级调度算法之一。

4.1 核心原理:周期越短,优先级越高

RMS的原理,一句话就能说清楚:任务的周期越短,它的优先级就越高

你想想看,周期短意味着什么?意味着它更频繁地需要CPU。如果它优先级低,很容易被长周期任务堵住,导致错过截止时间。所以RMS的做法很直接——谁急谁先跑。

我个人习惯把这种思路叫做「按心跳快慢排座次」。心跳快的,坐前排;心跳慢的,往后靠。

核心思想: 任务优先级与周期成反比。周期 T 越小,优先级 P 越高。

4.2 优先级分配规则

分配规则其实就一条公式:

若 T_i < T_j,则 P_i > P_j

翻译成人话:任务i的周期比任务j短,那么任务i的优先级就比任务j高。

这里有个细节要注意——优先级是静态的。一旦分配好,系统运行期间不会改变。这和EDF那种动态调度完全不同。

我曾经在一个数据采集项目里用过RMS。三个任务:一个采集传感器数据(周期10ms),一个做滤波处理(周期20ms),一个负责日志记录(周期100ms)。按照RMS,采集任务优先级最高,滤波次之,日志最低。跑起来很稳,从来没出过问题。

避坑指南: 我曾经犯过一个错——把中断服务程序的优先级也按RMS分配。结果发现中断太频繁,把普通任务饿死了。记住:RMS只适用于周期性任务,中断处理要单独考虑。

4.3 可调度性判定

这是RMS最硬核的部分。你分配好优先级,怎么知道系统能不能跑起来?

这里有两个判定方法:

4.3.1 充分条件:刘-莱兰条件(Liu & Layland)

这是最经典的判定公式:

U = Σ (C_i / T_i) ≤ n * (2^(1/n) - 1)

其中:

  • U 是CPU利用率
  • C_i 是任务i的最坏执行时间
  • T_i 是任务i的周期
  • n 是任务数量

当n趋向无穷大时,这个上界收敛到约69.3%。也就是说,如果CPU利用率不超过69%,RMS一定能调度。但超过69%呢?不一定,得看具体情况。

任务数 n 利用率上界
1 100%
2 82.8%
3 77.9%
4 75.6%
5 74.3%
69.3%
注意: 这个条件是充分但不必要的。也就是说,满足它一定能调度;但不满足它,也不一定不能调度。我见过很多项目,利用率跑到85%照样跑得好好的,但前提是任务周期之间是谐波关系。

4.3.2 精确判定:响应时间分析

如果你觉得69%太保守,可以用更精确的方法——响应时间分析。公式如下:

R_i = C_i + Σ (ceil(R_i / T_j) * C_j)   (对优先级高于i的所有任务j求和)

这个公式需要迭代计算。先假设R_i = C_i,然后不断代入右边,直到收敛。如果最终R_i ≤ T_i,说明任务i可调度。

嗯,这里要注意:迭代可能不收敛。如果R_i越算越大,超过T_i还没稳定,那就说明不可调度。

我的经验: 实际项目中,我一般先用刘-莱兰条件做个快速筛选。如果通过,直接放心用。如果没通过,再用响应时间分析做精确判定。这样既快又准。

4.4 优缺点分析

任何算法都有两面性。RMS也不例外。

4.4.1 优点

  • 实现简单: 优先级静态分配,运行时开销极小。说白了,就是比较一下周期大小,完事。
  • 可预测性强: 固定优先级意味着行为可预判。这在安全关键系统里非常重要。
  • 理论成熟: 有严格的可调度性判定条件,不像某些算法全靠经验。
  • 适合硬实时: 只要通过判定,就能保证所有任务在截止时间前完成。

4.4.2 缺点

  • CPU利用率不高: 理论上界只有69.3%。实际中虽然能更高,但总归有天花板。
  • 对周期敏感: 如果任务周期不是谐波关系,利用率上界会更低。
  • 不适用于非周期任务: 突发任务、偶发任务,RMS处理起来很麻烦。
  • 优先级反转: 低优先级任务持有资源,高优先级任务等待,导致优先级反转。需要配合优先级继承协议使用。
总结: RMS是硬实时系统的「基本功」。它不完美,但足够可靠。我建议每个做实时系统的工程师,都先把RMS吃透。因为很多更复杂的调度算法,本质上都是在RMS基础上做改进。

好了,RMS的核心内容就这些。下一章咱们聊聊EDF——最早截止时间优先调度。那家伙更灵活,但坑也更多。到时候再细说。