【硬实时嵌入式系统多任务调度-----系统调度系列(一)】用 RMA 算清你的 CPU 还能扛多少任务
1. 问题背景:我到底还能再加多少功能?
假设你在做这样一个典型场景:
- MCU:STM32 系列(例如 100 MHz 主频)
- 外设:
- 一个通过 SPI 接口输出的双通道 ADC,用来高速采样模拟信号
- 若干 UART/I2C 设备(传感器、调试口等)
- 上层应用:
- 滤波算法、控制算法
- 通信协议栈(比如 Modbus/CAN/自定义协议)
- 一些定时任务(看门狗、状态上报等)
常见的几个实际问题:
- 在当前采样与控制任务已经存在的情况下,还能否增加新的采样通道或提高采样率?
- 再加一个周期 1 ms 的控制循环,会不会把系统搞崩?
- I2C、UART、USB 等驱动 + 上层应用一起跑时,怎么量化“占用多少 CPU”?
- 在已有通信协议和日志任务基础上,还能否集成更复杂的上层应用逻辑?
这类问题的本质是:
在给定硬件资源(CPU 主频、总线带宽等)和实时性要求下,
新增功能对应的任务集合是否仍然“可调度”,从而保证所有关键任务按时完成?
为了严谨回答这一问题,我们需要一个明确的任务模型与可调度性判据,这正是 RMA 能提供的工具。
2. 周期任务直观模型与 CPU 利用率
2.1 把工程里的“功能”抽象成“任务”
为了回答“还能不能再加一个功能”这个问题,第一步是把功能抽象成一组周期任务,并能粗略估算每个任务大约吃掉多少 CPU 时间。
在实时调度理论中,典型做法是把系统拆成一堆周期任务:
- 每隔一段时间要执行一次(例如每 100 µs、1 ms、10 ms 等);
- 每次真正占用 CPU 的时间是一个有限的时间片(例如 5 µs、50 µs、200 µs 等)。
我们把这两件事分别记为:
- 周期(或触发间隔) T i T_i Ti:两次执行之间的时间间隔;
- 执行时间 C i C_i Ci:每次执行时实际占用 CPU 的时间。
在工程中,可以用具体例子来理解:
-
任务 1:ADC+SPI 数据采集任务
- 每隔 T 1 = 100 μ s T_1 = 100\,\mu s T1=100μs 采样一次(10 kHz 采样率)
- 每次采样后:中断/ DMA 回调里做数据拷贝和简单预处理,耗时约 C 1 = 5 μ s C_1 = 5\,\mu s C1=5μs
-
任务 2:控制算法任务
- 每隔 T 2 = 1 m s T_2 = 1\,ms T2=1ms 运行一次控制律
- 每次运行耗时 C 2 = 50 μ s C_2 = 50\,\mu s C2=50μs
-
任务 3:通信协议任务
- 每隔 T 3 = 10 m s T_3 = 10\,ms T3=10ms 打包数据并通过 UART/以太网发送
- 每次耗时 C 3 = 200 μ s C_3 = 200\,\mu s C3=200μs
这样,每个“功能”就可以用一对 ( C i , T i ) (C_i, T_i) (Ci,Ti) 来描述:
周期任务 i i i:每隔 T i T_i Ti 时间触发一次,每次占用 CPU 时间 C i C_i Ci。
后续所有关于 CPU 利用率和可调度性的分析,都是在这个简单模型之上展开的。
2.2 利用率公式: U = C / T U = C/T U=C/T 的物理意义
在一段很长时间内(比如 100ms ),任务 i i i 会执行 100 ms T i \dfrac{100\,\text{ms}}{T_i} Ti100ms 次,每次耗时 C i C_i Ci。因此:
任务 i 每100ms总耗时 = C i ⋅ 100 ms T i \text{任务 }i\text{ 每100ms总耗时} = C_i \cdot \frac{100\,\text{ms}}{T_i} 任务 i 每100ms总耗时=Ci⋅Ti100ms
此任务的CPU 利用率(这个任务吃掉的 CPU 比例)就是:
U i = 任务 i 每100ms总耗时 100 ms = C i T i U_i = \frac{\text{任务 }i\text{ 每100ms总耗时}}{100\,\text{ms}} = \frac{C_i}{T_i} Ui=100ms任务 i 每100ms总耗时=TiCi
简单来说,就是在t时间段内执行这个任务消耗的时间可以简单的用
cpu spend time = t ⋅ C i T i \text{cpu spend time} = t \cdot \frac{C_i}{T_i} cpu spend time=t⋅TiCi
从物理直觉上看,在每个周期长度为 T i T_i Ti 的时间窗口内,任务 i i i 仅在长度约为 C i C_i Ci 的子区间内占用 CPU,其在一个周期内部的“占空比”(duty cycle)即为 C i / T i C_i/T_i Ci/Ti。当该周期行为长期重复时,这个占空比在统计意义上收敛为任务的 CPU 利用率。
代入上面的例子(为了方便算,用毫秒):
-
任务 1: T 1 = 0.1 m s , C 1 = 0.005 m s T_1 = 0.1\,ms,\ C_1 = 0.005\,ms T1=0.1ms, C1=0.005ms
U 1 = 0.005 0.1 = 0.05 = 5 % U_1 = \frac{0.005}{0.1} = 0.05 = 5\% U1=0.10.005=0.05=5% -
任务 2: T 2 = 1 m s , C 2 = 0.05 m s T_2 = 1\,ms,\ C_2 = 0.05\,ms T2=1ms, C2=0.05ms
U 2 = 0.05 1 = 0.05 = 5 % U_2 = \frac{0.05}{1} = 0.05 = 5\% U2=10.05=0.05=5% -
任务 3: T 3 = 10 m s , C 3 = 0.2 m s T_3 = 10\,ms,\ C_3 = 0.2\,ms T3=10ms, C3=0.2ms
U 3 = 0.2 10 = 0.02 = 2 % U_3 = \frac{0.2}{10} = 0.02 = 2\% U3=100.2=0.02=2%
总利用率:
U total = U 1 + U 2 + U 3 = 0.05 + 0.05 + 0.02 = 0.12 = 12 % U_{\text{total}} = U_1 + U_2 + U_3 = 0.05 + 0.05 + 0.02 = 0.12 = 12\% Utotal=U1+U2+U3=0.05+0.05+0.02=0.12=12%
这意味着:在长期平均意义上,CPU 只有大约 12% 的时间在处理这三个任务,其余 88% 的时间可留给其它任务、中断或未来新功能。
3. 功能扩展问题与可调度性判定
基于第 1 节的问题背景和第 2 节的任务模型,我们可以把“还能不能再加一个功能”形式化为一个可调度性判定问题:
在现有这一组周期任务的基础上加入一个或多个新任务后, 在给定调度策略(本文主要讨论 RM)下,扩展后的任务集合是否仍然能够让所有任务按时完成?
在嵌入式/实时系统设计中,这类问题常表现为:
- 在现有控制与采样任务之上,增加新的周期性控制任务(例如额外的 1 ms 闭环);
- 在固定 MCU 平台上,提高 ADC 采样率或增加采样通道;
- 在已有通信与日志任务基础上,集成更复杂的协议栈或上层应用逻辑。
如果扩展后的任务集合在调度策略下仍然可调度(schedulable),则从实时性角度看,该功能扩展在当前硬件资源约束下是可行的;反之,则意味着在某些最坏情况下会有任务无法按时完成,需要调整周期、优化实现或升级平台。
在实时调度理论中,“可调度”可以用更精确但仍然直观的方式来理解:
在某种调度策略下,如果对系统中每一个周期任务来说,它的每一次执行都能够在下一次触发之前完成,那么我们就说这组任务在该调度策略下是可调度的。
换句话说,在本文所讨论的典型场景中,我们只考虑最常见的约束:
每个任务在每个周期内都必须“从开始到完成”,不能拖到下一个周期,否则就视为未按时完成。
形式化的任务模型与“截止时间”等符号化定义会在第 5.0 节中给出,这里暂时保持直观描述,便于与工程经验对应。
从工程角度来看:
- 如果“现有任务 + 新功能”这整套东西是可调度的,那么即使在系统最忙、所有中断都往一块儿挤的最坏情况下,控制回路也不会莫名其妙掉帧,采样不会丢点,通信不会经常超时——换句话说,这个新功能在时间维度上是“扛得住”的;
- 如果不可调度,你就要预期:在某些极端时刻,低优先级的控制或通信任务可能被挤到来不及运行,表现为偶尔卡顿、控制发飘、采样/通信偶发异常,需要调整周期、优化实现或者换更强的芯片。
在后续第 4–5 节中,我们将通过 RM/RMA 的若干经典结论,给出判定“是否可调度”的实用方法,从而回答“能不能加新功能”的问题。
4. Rate Monotonic (RM) / RMA:基本概念与主要结论
本节给出 Rate Monotonic(RM)和 Rate Monotonic Analysis(RMA)的核心术语和结论,用于建立整体概念框架;详细推导和例子放在第 5 节,读者若只需要结论,可阅读完本节后直接跳到第 6 节。
先把这两个缩写的关系说清楚:
- RM(Rate Monotonic):一种具体的调度策略/固定优先级分配规则——规定“谁的优先级更高、谁可以抢占谁”;
- RMA(Rate Monotonic Analysis):在采用 RM 这套调度策略的前提下,用来分析“这组任务到底能不能按时完成”的一整套方法和数学结论(例如利用率上界、响应时间分析等)。
简单说:RM 是“怎么玩”,RMA 是“怎么算清楚能不能玩得转”。
在 RM 固定优先级调度中,规则很简单:
- 周期短的任务优先级高;
- 高优先级可以随时抢占低优先级。
比如:
- T 1 = 1 m s T_1 = 1\,ms T1=1ms → 优先级最高
- T 2 = 5 m s T_2 = 5\,ms T2=5ms
- T 3 = 20 m s T_3 = 20\,ms T3=20ms → 优先级最低
这个和嵌入式系统的任务调度高度符合,往往开发人员会人为的定义任务的优先级。这就对应了工程上的常识:快速闭环控制(周期短)比慢速的监控/通信(周期长)更“紧急”,必须优先保证。
在此基础上,RMA(Rate Monotonic Analysis)给出了一系列关于可调度性的经典结论。为了后文方便,这里以定理形式列出两个最常用的结果(在第 5 节中会给出推导思路).
定理 1(Liu–Layland 利用率上界定理)
在 Liu–Layland 周期任务模型下,对采用 RM 调度的 n n n 个周期任务,如果总利用率满足
U = ∑ i = 1 n C i T i ≤ n ( 2 1 / n − 1 ) , U = \sum_{i=1}^n \frac{C_i}{T_i} \le n\bigl(2^{1/n} - 1\bigr), U=i=1∑nTiCi≤n(21/n−1),
则该任务集合在 RM 下一定可调度。特别地,当 n → ∞ n \to \infty n→∞ 时,上界收敛为
lim n → ∞ n ( 2 1 / n − 1 ) = ln 2 ≈ 0.693. \lim_{n\to\infty} n(2^{1/n}-1) = \ln 2 \approx 0.693. n→∞limn(21/n−1)=ln2≈0.693.
因此,在任务数较多且周期结构未知的情况下, U ≤ 69.3 % U \le 69.3\% U≤69.3% 可以作为一条保守而统一的“安全线”。
如果把上面这个不等式拆开来看:
- 左边 U = ∑ C i / T i U = \sum C_i/T_i U=∑Ci/Ti 是“实际吃掉的 CPU 总比例”:第 i i i 个任务每个周期占用 C i C_i Ci 时间、周期是 T i T_i Ti,于是它长期平均占用的 CPU 比例就是 C i / T i C_i/T_i Ci/Ti,把所有任务加起来就是总负载;
- 右边 n ( 2 1 / n − 1 ) n(2^{1/n}-1) n(21/n−1) 可以理解成对“在最坏搭配下,这台 CPU 最多能安全承受多少总负载”的一个理论上界,它只跟任务数量 n n n 有关,不管具体周期怎么搭配;
- 条件“ U U U 不超过右边”就等价于说:当前这组任务对 CPU 的总压力,没有超过这套理论给出的最坏情况下“安全承载能力”。当然,这是充分条件而不是必要条件。
所以,这个不等式的工程读法可以简化成一句话:
只要你现在这堆任务的总利用率不超过这条“安全线”,就可以放心地认为:在 RM 调度下,它们排得过来。
工程上的理
解和用法(定理 1)
可以把这条定理看成一根“总负载安全线”:
- 操作上,你只需要:统计所有周期任务的 C i , T i C_i, T_i Ci,Ti,算出各自的 U i = C i / T i U_i = C_i/T_i Ui=Ci/Ti,再求和得到 U U U;
- 对比上界 U max ( n ) = n ( 2 1 / n − 1 ) U_{\max}(n) = n(2^{1/n}-1) Umax(n)=n(21/n−1)(或者偷懒直接用 0.693 0.693 0.693 作为统一上界)。
如果 U U U 明显小于这个上界,就可以理解为:即使所有任务在最不利的时间点互相重叠,RM 也排得过来,不会因为 CPU 忙不过来而“挤爆”某个任务。
例如,假设一个系统里有 5 个周期任务,总利用率 U ≈ 40 % U \approx 40\% U≈40%,远小于 5 ( 2 1 / 5 − 1 ) ≈ 0.67 5(2^{1/5}-1) \approx 0.67 5(21/5−1)≈0.67,那么从调度角度看就是宽裕的,此时再增加一些轻量的新功能通常是没问题的。
定理 2(响应时间可调度性判据)
对于第 i i i 个任务,其最坏响应时间 R i R_i Ri 可通过迭代形式
R i ( k + 1 ) = C i + ∑ j ∈ h p ( i ) ⌈ R i ( k ) T j ⌉ C j R_i^{(k+1)} = C_i + \sum_{j \in hp(i)} \left\lceil \frac{R_i^{(k)}}{T_j} \right\rceil C_j Ri(k+1)=Ci+j∈hp(i)∑⌈TjRi(k)⌉Cj
这里每一项的含义可以拆开理解:
- R i R_i Ri:任务 i i i 的“最坏响应时间”,也就是从“这次该轮到它执行”到“它这次真的做完”为止,在最极端抢占情况下可能拖多久(我们暂时估计任务i,在所有触发里,最糟糕的那一次,从被触发到干完一共拖了多久,比如这个任务本身只需要50us,但是因为有更高优先级的任务,最糟糕的那一次运行了7ms才会运行完这一次任务, R i ( k ) R_i^{(k)} Ri(k) 意思是在第k轮计算时候,对这个最坏值Ri的猜测和期望, k = 0 k=0 k=0:先乐观一点,假设没人打断, R i ( k ) R_i^{(k)} Ri(k) = C ( i ) C_{(i)} C(i)),带入公式算出高优先级打断后,得到更现实一点的 R i ( 1 ) R_i^{(1)} Ri(1),再次迭代得到 R i ( 2 ) R_i^{(2)} Ri(2)等等;
- R i ( k ) R_i^{(k)} Ri(k) / R i ( k + 1 ) R_i^{(k+1)} Ri(k+1):用迭代法一轮一轮逼近真正的 R i R_i Ri——第 k k k 轮的估计值是 R i ( k ) R_i^{(k)} Ri(k),带入公式得到下一轮估计 R i ( k + 1 ) R_i^{(k+1)} Ri(k+1);
- h p ( i ) hp(i) hp(i):所有比任务 i i i 优先级高的任务集合;
- T j T_j Tj:高优先级任务 j j j 的周期;
- ⌈ R i ( k ) T j ⌉ \left\lceil \dfrac{R_i^{(k)}}{T_j} \right\rceil ⌈TjRi(k)⌉:在一个长度为 R i ( k ) R_i^{(k)} Ri(k) 的时间窗口里,任务 j j j 最多可能被触发多少次。比如 R i ( k ) = 7 m s R_i^{(k)} = 7ms Ri(k)=7ms、 T j = 3 m s T_j = 3ms Tj=3ms, 7 / 3 ≈ 2.33 7/3 \approx 2.33 7/3≈2.33,向上取整得到 3,表示“最多可能插进来 3 次”;
- ⌈ R i ( k ) T j ⌉ C j \left\lceil \dfrac{R_i^{(k)}}{T_j} \right\rceil C_j ⌈TjRi(k)⌉Cj:在这段时间里,任务 j j j 这些触发实例一共占用 CPU 的时间;
- 对所有 j ∈ h p ( i ) j \in hp(i) j∈hp(i) 进行求和,就是“所有高优先级任务在这段时间里一共抢走了多少 CPU 时间”;
- 再加上任务 i i i 自己的执行时间 C i C_i Ci,就得到一个新的估计 R i ( k + 1 ) R_i^{(k+1)} Ri(k+1):
任务 i i i 从准备执行开始,到真正做完 = 自己要用的时间 C i C_i Ci + 这期间被所有更高优先级任务打断所消耗的时间。
之所以要用迭代形式,是因为一开始并不知道真正的 R i R_i Ri 是多少,只能先猜一个初值(最简单就是 R i ( 0 ) = C i R_i^{(0)} = C_i Ri(0)=Ci,假设暂时没有被抢占),算出高优先级任务可能插进来的干扰,再反过来修正“那它这次其实要拖这么久才能做完”,一轮一轮逼近最终的最坏情况。
求解。当迭代收敛到某个 R i R_i Ri 且满足 R i R_i Ri 不超过该任务自己的周期(在本文假设下,周期就等于它的截止时间) 时,可以认为这个任务在给定优先级分配下是可调度的;若对所有任务 i i i 均满足这一条件,则整个任务集可调度。实践中,该响应时间分析常用于对接近或略高于利用率上界的任务集合做精细判定。
工程上的理解和用法(定理 2)
可以把 R i R_i Ri 理解成:“这次从被触发到真正干完,最极端情况下最多要拖多久?” 工程上通常这么用:
- 先按周期长短给任务排好 RM 优先级(周期越短,优先级越高);
- 选一个你关心的任务 i i i,取初值 R i ( 0 ) = C i R_i^{(0)} = C_i Ri(0)=Ci,带入上面的公式一轮一轮迭代,直到前后两次结果几乎不变;
- 看最终的 R i R_i Ri 是否小于这个任务自己设定的周期(或截止时间)。
如果所有关键任务算出来的 R i R_i Ri 都小于自己的周期,那就可以理解为:在最坏情况下,高优先级怎么挤、怎么抢占,系统也来得及把这些关键任务做完。这比单纯看“总利用率差不多还行”要严格得多。
上述两个结论在工程上提供了一个分层使用的思路:
- 粗略评估时,可先使用定理 1 进行“快速筛查”:若总利用率明显低于上界(特别是低于约 69.3%),则调度上通常无需过度担心;
- 当总利用率接近甚至略超过上界,或任务结构较复杂时,可进一步采用定理 2 的响应时间分析,对关键任务逐个进行严格判定。
5. RMA 利用率上界:从公式到例子再到证明
(如果直接应用可跳过本节)
这一节把几件事放在一起讲清楚:
- 上界公式长什么样,69.3% 到底是什么;
- 几个具体例子帮你建立直觉:什么时候肯定安全、什么时候要小心;
- 这个上界大致是怎么“推”出来的(工程师视角的直觉证明);
5.1 周期任务模型与假设(Liu–Layland 模型)
在更严格的分析中,我们通常采用 Liu–Layland 周期任务模型对系统进行抽象。为便于后续推导,这里给出模型与假设的简要说明(一般读者可以略读,仅将其视为第 2 节直观模型的形式化版本)。
- 任务集记为 τ = { τ 1 , τ 2 , … , τ n } \tau = \{\tau_1, \tau_2, \dots, \tau_n\} τ={τ1,τ2,…,τn};
- 每个周期任务 τ i \tau_i τi 由三元组 ( C i , T i , D i ) (C_i, T_i, D_i) (Ci,Ti,Di) 表示,其中:
- C i C_i Ci:任务 τ i \tau_i τi 的最坏执行时间(worst-case execution time, WCET);
- T i T_i Ti:任务 τ i \tau_i τi 的周期或最小到达间隔;
- D i D_i Di:相对截止时间(相对于释放时刻,任务必须完成的最晚时间)。
典型假设包括:
- 所有任务为独立的周期任务,不存在共享资源引起的阻塞(或阻塞时间已合并入 C i C_i Ci);
- 采用抢占式、固定优先级调度(preemptive fixed-priority);
- 截止时间等于周期,即 D i = T i D_i = T_i Di=Ti;
- 任务的 WCET C i C_i Ci 已通过分析或测量获得并被视为确定量;
- 调度开销、上下文切换等可以忽略或并入 C i C_i Ci 中。
在该模型下,任务 τ i \tau_i τi 的利用率定义为:
U i = C i T i , U = ∑ i = 1 n U i , U_i = \frac{C_i}{T_i}, \qquad U = \sum_{i=1}^n U_i, Ui=TiCi,U=i=1∑nUi,
其中 U U U 为整个任务集对 CPU 的总利用率。这一形式化定义与第 2 节给出的直观解释是一致的,只是表达得更适合数学推导。
5.2 上界公式:69.3% 安全线从哪来?
Liu & Layland 告诉我们,对 RM 调度的 n n n 个周期任务,若总利用率:
U = ∑ i = 1 n C i T i U = \sum_{i=1}^n \frac{C_i}{T_i} U=i=1∑nTiCi
满足:
U ≤ n ( 2 1 / n − 1 ) U \le n\left(2^{1/n}-1\right) U≤n(21/n−1)
那么这组任务在 RM 下是 一定可调度的。这里是“一定”——也就是一个充分条件。
当任务数很多时:
lim n → ∞ n ( 2 1 / n − 1 ) = ln 2 ≈ 0.693 \lim_{n\to\infty} n(2^{1/n}-1) = \ln 2 \approx 0.693 n→∞limn(21/n−1)=ln2≈0.693
所以,69.3% 就是:
当你任务数多、周期关系可能很乱、而你又想用一条简单统一的“安全线”时,
只要总利用率不超过 69.3%,在 RM 下就一定可调度。
这并不是说“超过 69.3% 就一定挂”,而是说“超过之后,这个简单公式不能再保证所有情况都安全”。
在工程里,你可以把它理解成:
- 想用最简单的方式回答“还能不能加功能?”:
把新功能抽象成新任务,算上所有 U i U_i Ui 后,如果 U total U_{\text{total}} Utotal 还远小于 69.3%,那基本可以说 调度上没问题,瓶颈更多在带宽、存储等别的地方。
公式证明如下:
需要事先接受两个经典结论(它们在实时系统教材里都有完整证明,这里不再从头推):
- 临界时刻定理(critical instant theorem):
在 RM 调度下,某个任务的最坏响应时间,一定发生在“它自己和所有更高优先级任务同时释放”的那个时刻附近。 - 最坏响应时间的递推不等式:
若任务按周期从小到大编号(也就是 RM 优先级从 1 到 n n n),第 k k k 个任务的最坏响应时间 R k R_k Rk 满足
R k = C k + ∑ i = 1 k − 1 ⌈ R k T i ⌉ C i R_k = C_k + \sum_{i=1}^{k-1} \left\lceil \frac{R_k}{T_i} \right\rceil C_i Rk=Ck+i=1∑k−1⌈TiRk⌉Ci
含义是:
“这次轮到 k k k 执行到它真正做完”为止,
= 自己执行时间 C k C_k Ck + 在这段时间内所有高优先级任务反复触发抢占所占用的时间总和。
我们的目标是:在 D i = T i D_i = T_i Di=Ti 的假设下,推导出一个只依赖各任务利用率 U i = C i / T i U_i = C_i/T_i Ui=Ci/Ti 的“足够条件”,保证对所有 k k k 都有 R k ≤ T k R_k \le T_k Rk≤Tk,从而得到总利用率的上界。
5.2.1 第一步:放松取整,得到可解的不等式
先对上面的递推关系做一个宽松但简单的放大:
⌈ R k T i ⌉ ≤ R k T i + 1 \left\lceil \frac{R_k}{T_i} \right\rceil \le \frac{R_k}{T_i} + 1 ⌈TiRk⌉≤TiRk+1
代回:
R k ≤ C k + ∑ i = 1 k − 1 ( R k T i + 1 ) C i = C k + R k ∑ i = 1 k − 1 C i T i + ∑ i = 1 k − 1 C i . \begin{aligned} R_k &\le C_k + \sum_{i=1}^{k-1} \left( \frac{R_k}{T_i} + 1 \right) C_i \\ &= C_k + R_k \sum_{i=1}^{k-1} \frac{C_i}{T_i} + \sum_{i=1}^{k-1} C_i. \end{aligned} Rk≤Ck+i=1∑k−1(TiRk+1)Ci=Ck+Rki=1∑k−1TiCi+i=1∑k−1Ci.
记 U i = C i / T i U_i = C_i/T_i Ui=Ci/Ti,则:
R k ≤ C k + R k ∑ i = 1 k − 1 U i + ∑ i = 1 k − 1 C i . R_k \le C_k + R_k \sum_{i=1}^{k-1} U_i + \sum_{i=1}^{k-1} C_i. Rk≤Ck+Rki=1∑k−1Ui+i=1∑k−1Ci.
把含 R k R_k Rk 的项移到左边:
R k ( 1 − ∑ i = 1 k − 1 U i ) ≤ C k + ∑ i = 1 k − 1 C i . R_k \Bigl(1 - \sum_{i=1}^{k-1} U_i\Bigr) \le C_k + \sum_{i=1}^{k-1} C_i. Rk(1−i=1∑k−1Ui)≤Ck+i=1∑k−1Ci.
只要 ∑ i = 1 k − 1 U i < 1 \sum_{i=1}^{k-1} U_i < 1 ∑i=1k−1Ui<1(这是合理的,因为高优先级任务自己也得可调度),就可以两边同时除以 1 − ∑ i = 1 k − 1 U i 1 - \sum_{i=1}^{k-1} U_i 1−∑i=1k−1Ui,得到:
R k ≤ C k + ∑ i = 1 k − 1 C i 1 − ∑ i = 1 k − 1 U i . R_k \le \frac{C_k + \sum_{i=1}^{k-1} C_i}{1 - \sum_{i=1}^{k-1} U_i}. Rk≤1−∑i=1k−1UiCk+∑i=1k−1Ci.
这一步的要点是:我们用“把天花板函数 ⌈ ⋅ ⌉ \lceil\cdot\rceil ⌈⋅⌉ 换成线性函数”的方式,得到一个更宽松但可解的上界——只要这个上界本身不超过 T k T_k Tk,那真实的 R k R_k Rk 就一定不超过 T k T_k Tk。
5.2.2 第二步:把不等式改写成只含 U i U_i Ui 的形式
为了最终得到一个只跟 U i U_i Ui 有关、跟具体 T i T_i Ti 无关的判据,我们把右边分子中的 C i C_i Ci 都除以 T k T_k Tk:
R k T k ≤ C k + ∑ i = 1 k − 1 C i T k ( 1 − ∑ i = 1 k − 1 U i ) . \frac{R_k}{T_k} \le \frac{C_k + \sum_{i=1}^{k-1} C_i}{T_k\Bigl(1 - \sum_{i=1}^{k-1} U_i\Bigr)}. TkRk≤Tk(1−∑i=1k−1Ui)Ck+∑i=1k−1Ci.
对 RM 来说,我们按周期从小到大编号:
T 1 ≤ T 2 ≤ ⋯ ≤ T k . T_1 \le T_2 \le \dots \le T_k. T1≤T2≤⋯≤Tk.
因此对任意 i ≤ k i \le k i≤k,有 T i ≤ T k T_i \le T_k Ti≤Tk,从而:
C i T k = C i T i ⋅ T i T k = U i ⋅ T i T k ≤ U i . \frac{C_i}{T_k} = \frac{C_i}{T_i} \cdot \frac{T_i}{T_k} = U_i \cdot \frac{T_i}{T_k} \le U_i. TkCi=TiCi⋅TkTi=Ui⋅TkTi≤Ui.
于是
C k + ∑ i = 1 k − 1 C i T k = C k T k + ∑ i = 1 k − 1 C i T k ≤ U k + ∑ i = 1 k − 1 U i = ∑ i = 1 k U i . \frac{C_k + \sum_{i=1}^{k-1} C_i}{T_k} = \frac{C_k}{T_k} + \sum_{i=1}^{k-1} \frac{C_i}{T_k} \le U_k + \sum_{i=1}^{k-1} U_i = \sum_{i=1}^{k} U_i. TkCk+∑i=1k−1Ci=TkCk+i=1∑k−1TkCi≤Uk+i=1∑k−1Ui=i=1∑kUi.
代回上式,得到一个更宽松但只含 U i U_i Ui 的不等式:
R k T k ≤ ∑ i = 1 k U i 1 − ∑ i = 1 k − 1 U i . \frac{R_k}{T_k} \le \frac{\sum_{i=1}^{k} U_i}{1 - \sum_{i=1}^{k-1} U_i}. TkRk≤1−∑i=1k−1Ui∑i=1kUi.
在我们的假设下,要保证任务 τ k \tau_k τk 在 RM 下可调度,只要保证
R k T k ≤ 1 \frac{R_k}{T_k} \le 1 TkRk≤1
就够了(因为 D k = T k D_k = T_k Dk=Tk)。因此一个足够条件是:
∑ i = 1 k U i 1 − ∑ i = 1 k − 1 U i ≤ 1. \frac{\sum_{i=1}^{k} U_i}{1 - \sum_{i=1}^{k-1} U_i} \le 1. 1−∑i=1k−1Ui∑i=1kUi≤1.
化简一下:
∑ i = 1 k U i ≤ 1 − ∑ i = 1 k − 1 U i ⟹ U k + 2 ∑ i = 1 k − 1 U i ≤ 1. \sum_{i=1}^{k} U_i \le 1 - \sum_{i=1}^{k-1} U_i \;\Longrightarrow\; U_k + 2\sum_{i=1}^{k-1} U_i \le 1. i=1∑kUi≤1−i=1∑k−1Ui⟹Uk+2i=1∑k−1Ui≤1.
这个不等式已经能给出一些“分段”的利用率条件(比如 k = 1 , 2 , 3 k=1,2,3 k=1,2,3 时分别约束 U 1 , U 2 , U 3 U_1,U_2,U_3 U1,U2,U3),但写成一般形式仍然不够直观。Liu–Layland 做了进一步的整理,使之变成一个漂亮的乘积形式。
5.2.3 第三步:先看两任务的完整推导,得到乘积约束
我们先完全算一遍 n = 2 n=2 n=2 的情况,这样乘积形式就不是“凭空掏出来”的了。
(1) 任务 1:
任务 1 没有高优先级任务干扰,最坏响应时间就是
R 1 = C 1 . R_1 = C_1. R1=C1.
可调度条件是 R 1 ≤ T 1 R_1 \le T_1 R1≤T1,也就是
U 1 = C 1 T 1 ≤ 1. U_1 = \frac{C_1}{T_1} \le 1. U1=T1C1≤1.
(2) 任务 2:
按照 5.2.1、5.2.2 的推导,对于 k = 2 k=2 k=2:
R 2 T 2 ≤ U 1 + U 2 1 − U 1 . \frac{R_2}{T_2} \le \frac{U_1 + U_2}{1 - U_1}. T2R2≤1−U1U1+U2.
可调度条件 R 2 ≤ T 2 R_2 \le T_2 R2≤T2 等价于
U 1 + U 2 1 − U 1 ≤ 1. \frac{U_1 + U_2}{1 - U_1} \le 1. 1−U1U1+U2≤1.
化简:
U 1 + U 2 ≤ 1 − U 1 ⟹ U 2 ≤ 1 − 2 U 1 . U_1 + U_2 \le 1 - U_1 \;\Longrightarrow\; U_2 \le 1 - 2U_1. U1+U2≤1−U1⟹U2≤1−2U1.
再带上 U 1 ≤ 1 U_1 \le 1 U1≤1,就得到两任务的一个可行区域。Liu–Layland 的巧妙之处在于,把它写成一个更压缩的形式:
( 1 + U 1 ) ( 1 + U 2 ) ≤ 2. (1+U_1)(1+U_2) \le 2. (1+U1)(1+U2)≤2.
我们来验证一下这两个条件之间的关系。展开乘积:
( 1 + U 1 ) ( 1 + U 2 ) = 1 + U 1 + U 2 + U 1 U 2 . (1+U_1)(1+U_2) = 1 + U_1 + U_2 + U_1U_2. (1+U1)(1+U2)=1+U1+U2+U1U2.
若要求
( 1 + U 1 ) ( 1 + U 2 ) ≤ 2 , (1+U_1)(1+U_2) \le 2, (1+U1)(1+U2)≤2,
等价于
U 1 + U 2 + U 1 U 2 ≤ 1. U_1 + U_2 + U_1U_2 \le 1. U1+U2+U1U2≤1.
在 U 1 ≤ 1 U_1 \le 1 U1≤1 的前提下,这个条件比前面的线性条件略强,但仍然是一个足够条件。直观地理解:
- 1 1 1 表示“有一个单位长度的窗口”(周期尺度);
- U 1 U_1 U1 是任务 1 在这个窗口里直接占用的比例;
- U 2 U_2 U2 是任务 2 在这个窗口里直接占用的比例;
- U 1 U 2 U_1U_2 U1U2 可以理解成“相互抢占、互相影响”带来的额外“放大”;
- 整体不超过 1,就能保证两者在最坏情况下也挤得下。
这就是 n = 2 n=2 n=2 时 ( 1 + U 1 ) ( 1 + U 2 ) ≤ 2 (1+U_1)(1+U_2) \le 2 (1+U1)(1+U2)≤2 的来历:它是由 R 1 ≤ T 1 , R 2 ≤ T 2 R_1 \le T_1, R_2 \le T_2 R1≤T1,R2≤T2 推导出来的一个稍微保守但很简洁的合成条件。
5.2.4 第四步:推广到 n n n 个任务,得到 ∏ ( 1 + U i ) ≤ 2 \prod (1+U_i) \le 2 ∏(1+Ui)≤2
对 n > 2 n>2 n>2 的情况,推导的模式和 n = 2 n=2 n=2 是类似的,只是代数会变长。Liu–Layland 的原始做法大致是:
- 假设前 k − 1 k-1 k−1 个任务已经可调度;
- 使用 5.5.1 和 5.5.2 中的步骤,写出 R k / T k R_k/T_k Rk/Tk 的上界不等式;
- 把“前 k − 1 k-1 k−1 个任务可调度”的条件代入,逐步整理公式;
- 最终得到一个形如
( 1 + U k ) ⋅ f ( U 1 , … , U k − 1 ) ≤ 2 (1+U_k) \cdot f(U_1,\dots,U_{k-1}) \le 2 (1+Uk)⋅f(U1,…,Uk−1)≤2
的递推关系;
- 通过归纳法,可以把它压缩成
∏ i = 1 n ( 1 + U i ) ≤ 2. \prod_{i=1}^{n} (1+U_i) \le 2. i=1∏n(1+Ui)≤2.
从工程使用角度看,你不需要记住中间每一步变形,只需要知道:
在 Liu–Layland 的假设下,如果 ∏ i = 1 n ( 1 + U i ) ≤ 2 \prod_{i=1}^{n} (1+U_i) \le 2 ∏i=1n(1+Ui)≤2 成立,那么这组任务在 RM 下一定可调度。
这是一个“只要满足就绝对安全”的乘积条件。
5.3 例子 1:总利用率远低于上界——非常安全
继续用第 2.1 节中“ADC+SPI 采样 / 控制算法 / 通信”的那个具体数字例子:
- 任务 1(ADC+SPI 采样): T 1 = 100 μ s , C 1 = 5 μ s T_1 = 100\,\mu s,\ C_1 = 5\,\mu s T1=100μs, C1=5μs → U 1 = 0.05 U_1 = 0.05 U1=0.05
- 任务 2(控制算法): T 2 = 1 m s , C 2 = 50 μ s T_2 = 1\,ms,\ C_2 = 50\,\mu s T2=1ms, C2=50μs → U 2 = 0.05 U_2 = 0.05 U2=0.05
- 任务 3(通信): T 3 = 10 m s , C 3 = 200 μ s T_3 = 10\,ms,\ C_3 = 200\,\mu s T3=10ms, C3=200μs → U 3 = 0.02 U_3 = 0.02 U3=0.02
总利用率:
U = 0.05 + 0.05 + 0.02 = 0.12 = 12 % U = 0.05 + 0.05 + 0.02 = 0.12 = 12\% U=0.05+0.05+0.02=0.12=12%
对于 n = 3 n = 3 n=3 个任务,RMA 上界是:
U max ( 3 ) = 3 ( 2 1 / 3 − 1 ) ≈ 3 ( 1.2599 − 1 ) ≈ 0.78 U_{\max}(3) = 3(2^{1/3}-1) \approx 3(1.2599 - 1) \approx 0.78 Umax(3)=3(21/3−1)≈3(1.2599−1)≈0.78
显然 0.12 ≪ 0.78 0.12 \ll 0.78 0.12≪0.78,更远小于 0.693 0.693 0.693。在这种情况下:
- 即使用 RM 的最简单规则,任务之间互相抢占,也很难导致“赶不完”;
- 你可以很有信心地说:“这几个任务对 CPU 压力几乎可以忽略”。
这是典型的:
工程中很多场景其实远远没到需要担心调度失败的地步,先估一下 U 就心里有数了。
5.3 例子 2:利用率接近/略超上界,但仍然可调度
- 任务 1: T 1 = 10 m s , C 1 = 2 m s T_1 = 10\,ms,\ C_1 = 2\,ms T1=10ms, C1=2ms → U 1 = 0.2 U_1 = 0.2 U1=0.2
- 任务 2: T 2 = 20 m s , C 2 = 4 m s T_2 = 20\,ms,\ C_2 = 4\,ms T2=20ms, C2=4ms → U 2 = 0.2 U_2 = 0.2 U2=0.2
- 任务 3: T 3 = 40 m s , C 3 = 8 m s T_3 = 40\,ms,\ C_3 = 8\,ms T3=40ms, C3=8ms → U 3 = 0.2 U_3 = 0.2 U3=0.2
它们的周期是谐波关系: 10 , 20 , 40 10, 20, 40 10,20,40,总利用率:
U = 0.2 + 0.2 + 0.2 = 0.6 = 60 % U = 0.2 + 0.2 + 0.2 = 0.6 = 60\% U=0.2+0.2+0.2=0.6=60%
对 n = 3 n = 3 n=3 的 RMA 上界是:
U max ( 3 ) ≈ 0.78 U_{\max}(3) \approx 0.78 Umax(3)≈0.78
所以 0.6 < 0.78 0.6 < 0.78 0.6<0.78,按公式:一定可调度。
如果我们稍微把任务 3 调“重”一点:
- 改为 C 3 = 12 m s C_3 = 12\,ms C3=12ms → U 3 = 12 / 40 = 0.3 U_3 = 12/40 = 0.3 U3=12/40=0.3
此时:
- 总利用率 U = 0.2 + 0.2 + 0.3 = 0.7 = 70 % U = 0.2 + 0.2 + 0.3 = 0.7 = 70\% U=0.2+0.2+0.3=0.7=70%
- 对比 ln 2 ≈ 69.3 % \ln 2 \approx 69.3\% ln2≈69.3%:略微超过了这条“通用安全线”。
但由于三个周期仍然是谐波(10,20,40),做精确的响应时间分析,会发现它 仍然可调度。也就是说:
即便 U > 69.3 % U > 69.3\% U>69.3%,在某些周期结构良好的情况下,系统仍然能正常按时完成所有任务。
这说明:
- 69.3% 是“永远不过分乐观的安全线”;
- 超过它不代表一定挂,只是需要具体分析。
5.3 例子 3:利用率看起来不高,但调度可能失败
再看一个“更诡异”的方向:
- 任务 1: T 1 = 7 , C 1 = 3 T_1 = 7,\ C_1 = 3 T1=7, C1=3 → U 1 ≈ 0.428 U_1 \approx 0.428 U1≈0.428
- 任务 2: T 2 = 8 , C 2 = 2 T_2 = 8,\ C_2 = 2 T2=8, C2=2 → U 2 = 0.25 U_2 = 0.25 U2=0.25
总利用率:
U ≈ 0.678 < 0.693 U \approx 0.678 < 0.693 U≈0.678<0.693
这里 U U U 仍然小于 69.3%。根据 Liu & Layland 的结论:
无论起始相位如何,这两个任务在 RM 下都应是可调度的。
接下来我们给一个更“扎心”的反例,展示“就算 U < 100 % U < 100\% U<100%,也未必可调度”。
构造两任务:
- 任务 1: T 1 = 3 , C 1 = 2 T_1 = 3,\ C_1 = 2 T1=3, C1=2 → U 1 = 2 / 3 ≈ 0.667 U_1 = 2/3 \approx 0.667 U1=2/3≈0.667;
- 任务 2: T 2 = 5 , C 2 = 1.5 T_2 = 5,\ C_2 = 1.5 T2=5, C2=1.5 → U 2 = 1.5 / 5 = 0.3 U_2 = 1.5/5 = 0.3 U2=1.5/5=0.3;
总利用率:
U = U 1 + U 2 ≈ 0.667 + 0.3 = 0.967 < 1. U = U_1 + U_2 \approx 0.667 + 0.3 = 0.967 < 1. U=U1+U2≈0.667+0.3=0.967<1.
看上去总利用率还没到 100%,似乎“CPU 理论上还有空闲”。但在 RM 下(周期短者优先,所以任务 1 优先级高于任务 2),我们对任务 2 做一次响应时间分析:
- 任务 1:没有更高优先级任务干扰,最坏响应时间就是 R 1 = C 1 = 2 ≤ T 1 = 3 R_1 = C_1 = 2 \le T_1 = 3 R1=C1=2≤T1=3,可调度。
- 任务 2:
-
初始估计 R 2 ( 0 ) = C 2 = 1.5 R_2^{(0)} = C_2 = 1.5 R2(0)=C2=1.5;
-
第 1 轮迭代:
R 2 ( 1 ) = C 2 + ⌈ R 2 ( 0 ) T 1 ⌉ C 1 = 1.5 + ⌈ 1.5 / 3 ⌉ ⋅ 2 = 1.5 + 1 ⋅ 2 = 3.5 ; R_2^{(1)} = C_2 + \Bigl\lceil \frac{R_2^{(0)}}{T_1} \Bigr\rceil C_1 = 1.5 + \bigl\lceil 1.5/3 \bigr\rceil \cdot 2 = 1.5 + 1\cdot 2 = 3.5; R2(1)=C2+⌈T1R2(0)⌉C1=1.5+⌈1.5/3⌉⋅2=1.5+1⋅2=3.5;
-
第 2 轮迭代:
R 2 ( 2 ) = C 2 + ⌈ R 2 ( 1 ) T 1 ⌉ C 1 = 1.5 + ⌈ 3.5 / 3 ⌉ ⋅ 2 = 1.5 + 2 ⋅ 2 = 5.5. R_2^{(2)} = C_2 + \Bigl\lceil \frac{R_2^{(1)}}{T_1} \Bigr\rceil C_1 = 1.5 + \bigl\lceil 3.5/3 \bigr\rceil \cdot 2 = 1.5 + 2\cdot 2 = 5.5. R2(2)=C2+⌈T1R2(1)⌉C1=1.5+⌈3.5/3⌉⋅2=1.5+2⋅2=5.5.
-
此时 R 2 ( 2 ) = 5.5 > T 2 = 5 R_2^{(2)} = 5.5 > T_2 = 5 R2(2)=5.5>T2=5,说明在最坏情况下,任务 2 这次从“轮到它”到“真正做完”会拖到 5.5 个时间单位,超过了自己的周期/截止时间 5,所以任务 2 在 RM 下是不可调度的。
这个例子把几件事说清楚了:
-
总利用率 U ≈ 96.7 % U \approx 96.7\% U≈96.7%,虽然还没到 100%,但任务 2 仍然会 miss deadline;
利用率只是在“长时间平均”意义上看 CPU 是否忙得过来, 但能不能在每个周期内按时完成,还严重依赖“周期怎么搭配、优先级怎么分、谁抢占谁”; -
对两任务来说,Liu–Layland 的安全线是
U max ( 2 ) = 2 ( 2 1 / 2 − 1 ) ≈ 0.828 , U_{\max}(2) = 2(2^{1/2}-1) \approx 0.828, Umax(2)=2(21/2−1)≈0.828,
而这个例子里的 U ≈ 0.967 > 0.828 U \approx 0.967 > 0.828 U≈0.967>0.828,正好落在“ U < 1 U<1 U<1 但已经超过安全线”的区域。
所以:
- “ U < 69.3 % U < 69.3\% U<69.3%” 是一个肯定安全的区域;
- “ 69.3 % < U < 100 % 69.3\% < U < 100\% 69.3%<U<100%” 里,有的任务集可以调度,有的则不行,
- 必须看周期结构和优先级分配,不能只看一个“CPU 使用率”。
- 如果任务数多、周期结构复杂,在 U ≈ 0.75 U \approx 0.75 U≈0.75 的总利用率下,既可能有“排得过来”的任务集,也可能有像上面那样“被抢占挤爆”的任务集——这时就需要用响应时间分析(或更一般的测试)来细算,而不能光看一个 U U U。
这也就是为什么我们需要像 RMA 这样的工具,来给出一个 保守但简单的“全局安全线”,再配合更精细的分析方法去处理那些落在灰色地带的情况。
–
6. 回到工程:怎么用这套理论评估你的系统?
6.1 步骤概览
-
把功能拆成任务:
- 驱动任务:ADC+SPI 采样、I2C 读取、UART 收发、USB 包处理等;
- 上层任务:控制律、滤波、协议栈、数据记录等。
-
估算或测量每个任务的执行时间 C i C_i Ci:
- 可用 DWT cycle counter、定时器等手段做实测;
- 或用经验值/数据手册做初估。
-
确定周期 T i T_i Ti:
- 如采样 10 kHz → T = 100 μ s T = 100\,\mu s T=100μs;
- 控制 1 kHz → T = 1 m s T = 1\,ms T=1ms;
- 状态上报 10 Hz → T = 100 m s T = 100\,ms T=100ms。
-
计算每个任务的利用率 U i = C i / T i U_i = C_i/T_i Ui=Ci/Ti,求总和 U U U。
-
用 RMA 上界做快速判断:
- 若任务数 n n n 不大,可以用 U max ( n ) = n ( 2 1 / n − 1 ) U_{\max}(n) = n(2^{1/n}-1) Umax(n)=n(21/n−1);
- 若任务数较多,又想偷懒——直接用 U ≤ 0.693 U \le 0.693 U≤0.693 做保守判断:
- U U U 明显低于 69.3%:非常安全;
- U U U 接近或略高于 69.3%:需要使用第 4 节中的定理 2(响应时间分析),对关键任务逐个计算最坏响应时间,并结合仿真/实测进行交叉验证。
-
考虑突发任务与余量:
- 一般工程实践会把周期任务的总利用率控制在 50%~60%;
- 剩下的留给偶发中断、后台任务、未来功能。
在实际工程里,这些分析手段可以配合使用:
- 先用定理 1 做一次“纸面粗筛”;
- 对边界情况或关键任务,用定理 2 做响应时间分析;
- 再用仿真或硬件在环测试(HIL)跑一段典型/最坏场景,看实际是否出现丢周期、抖动过大等现象;
- 如今也可以借助 AI 工具来减少算账和建模的机械工作:例如,把任务列表(每个任务的 C i , T i C_i, T_i Ci,Ti、优先级、是否关键任务等)整理成表格或结构化描述,明确告诉 AI:
- 先计算总利用率并与定理 1 对比;
- 再根据定理 2 为指定任务推导/迭代最坏响应时间;
- 如有需要,生成简单的离散时间调度仿真脚本(例如在 Python 中)并输出统计结果。
这样,工程师主要关注“模型是否真实、约束是否合理”,而把重复性的计算和仿真脚本生成交给工具处理。
6.2 “可调度”在工程上的含义
对于
在当前任务集合和调度策略(比如 RM)下,系统是可调度的。
它对应的工程含义就是:
- 所有关键周期任务,都能在周期(截止时间)之内稳定完成;
- 在最坏情况下(最糟糕的触发相位与干扰组合)也不会“挤爆”某个低优先级任务;
- 系统不会出现因为任务挤压导致的隐蔽时序 bug(比如控制算法偶尔“掉帧”、ADC 缓冲偶发溢出等)。
换句话说:
可调度 = 在设计假设的最坏情况下,所有关键任务都能按期完成,系统行为有理论保证,而不只是凭经验“感觉差不多”。
7. RM 的适用范围
前面几节我们几乎都在一个“理想的小世界”里讨论 RM/RMA:
- 单核 CPU;
- 抢占式、固定优先级;
- 独立的周期任务, C i , T i C_i, T_i Ci,Ti 已知, D i = T i D_i = T_i Di=Ti;
- 典型应用是 MCU + RTOS 之类相对简单的系统。
这一节单独拎出来,回答几个你在工程里一定会遇到的问题:
- RM 和 FIFO 调度、抢占式/非抢占式是什么关系?
- RM 主要用在硬实时还是软实时场景?
- 它跟 Linux 里的 CFS、SCHED_FIFO、SCHED_DEADLINE 等有啥关系?
- 如果是多核、异构、复杂系统,还有没有类似 RM 的模型?
7.1 RM、固定优先级、FIFO、抢占式的概念区分
先把几件经常混在一起说的东西拆开:
-
RM(Rate Monotonic):
- 本质是一个“优先级分配规则”:周期越短,优先级越高;
- 一旦按这个规则给所有任务定好了优先级,调度器就按照“高优先级先跑”的固定优先级策略运行。
-
固定优先级调度(fixed-priority scheduling):
- 只要求“每个任务有一个固定优先级”;
- 至于优先级怎么定,不管——RM 只是固定优先级的一种特定分配方式;
- 还可以有 Deadline Monotonic(截止时间越短优先级越高)等其他分配方式。
-
FIFO 调度:
- 如果在一个固定优先级系统里,对于“同一优先级”的多个任务,谁先到就先执行,直到它主动放弃 CPU 或被更高优先级抢占——这就对应“同优先级里 FIFO”;
- 比如 Linux 的 SCHED_FIFO:不同优先级之间是固定优先级抢占,同一优先级内部是 FIFO 排队。
-
抢占式 vs 非抢占式:
- RM 理论通常假设 抢占式固定优先级:高优先级任务一旦就绪,可以立刻打断正在运行的低优先级任务;
- 如果变成非抢占式(低优先级任务一旦开始就要跑完),则可调度性会变差,需要在响应时间分析中加上额外的阻塞项;
- 很多 RTOS(如 FreeRTOS、RTX 等)默认提供“抢占式固定优先级 + 同优先级 FIFO”的调度行为,非常适合实现 RM。
可以这样总结:
RM = 周期越短优先级越高 + 抢占式固定优先级调度;
操作系统层面通常用“抢占式固定优先级 + 同优先级 FIFO 队列”来具体实现它。
7.2 硬实时、软实时与 Linux 调度类(CFS / SCHED_FIFO / SCHED_DEADLINE)的概念
从“任务对截止时间的严格程度”来看,通常会区分:
-
硬实时(hard real-time):
- 任务一旦错过截止时间,就视为系统故障,后果可能严重(如电机失控、医疗设备异常等);
- RM/RMA 这套理论主要就是服务于硬实时场景:在最坏情况下也要保证每次都能按时完成。
-
软实时(soft real-time):
- 偶尔错过截止时间可以接受,只要整体统计行为尚可(如视频播放偶尔丢帧、网络服务偶尔超时);
- 此时更关心平均延迟、吞吐量、公平性等指标,未必需要像 RM 那样“次次有证明”。
Linux 内核里常见的几类调度策略,可以粗略对应到这些概念:
-
CFS(Completely Fair Scheduler):
- 默认调度类,追求“公平分享 CPU”,用虚拟运行时间(vruntime)来保证谁跑得少就多补偿一点;
- 很适合通用的桌面/服务器负载,但几乎不给你“硬实时保证”;
- 在 CFS 下,很难用 RM/RMA 这类理论做严格的可调度性分析——它不是为此设计的。
-
SCHED_FIFO / SCHED_RR(实时固定优先级类):
- 这两类才是真正“固定优先级 + 抢占式”的实时调度类:
- SCHED_FIFO:不同优先级之间是固定优先级抢占,同级内 FIFO;
- SCHED_RR:在 FIFO 的基础上,同级内再加一个轮转时间片。
- 如果你在 Linux 上想“尽量贴近 RM 模型”,通常会:
- 把关键周期任务放到 SCHED_FIFO/SCHED_RR;
- 周期越短的任务给更高优先级;
- 然后用 RMA 思路做一个近似分析(需要注意内核线程、中断等额外干扰)。
- 这两类才是真正“固定优先级 + 抢占式”的实时调度类:
-
SCHED_DEADLINE:
- 这是 Linux 中基于 Earliest Deadline First(EDF)+ 带约束的带宽预留(CBS)的调度类;
- 每个任务配置 ( r u n t i m e , d e a d l i n e , p e r i o d ) (runtime, deadline, period) (runtime,deadline,period) 参数,内核保证在这些参数下的 CPU 带宽约束;
- 在单核上,EDF 比 RM 更“强”:在同样假设下,能调度的任务集合至少不比 RM 少;
- 对 SCHED_DEADLINE,更适合使用 EDF 对应的分析工具(如 demand bound 函数、处理器需求模型等),而不是直接套 RM 的 69.3% 上界。
一句话概括:
- CFS:偏软实时/通用场景,难以做硬实时证明;
- SCHED_FIFO/SCHED_RR:固定优先级实时类,可用 RM/RMA 思路分析;
- SCHED_DEADLINE:EDF + 带宽预留,应该用 EDF 对应的实时分析方法。
7.3 RM 模型的局限性:为什么说它“简陋但有用”?
从模型假设来看,RM/RMA 确实“有点简陋”:
- 单核处理器;
- 抢占式固定优先级;
- 周期/最小间隔已知的周期或 sporadic 任务;
- 任务彼此独立,不共享资源(或阻塞时间已合并进 C i C_i Ci);
- 截止时间等于周期, D i = T i D_i = T_i Di=Ti;
- WCET C i C_i Ci 可知且相对稳定。
这套假设最典型的落地环境就是:
- MCU + RTOS(FreeRTOS、RTX、ThreadX 等);
- 简单的单核 SoC 上跑裸机/轻量 RTOS 的控制系统;
- 某些 FPGA/SoC 里跑在“控制核”(如 ARM Cortex-R)的实时控制任务。
一旦进入下面这些场景,RM 模型就会显得不够用:
- 多核或多处理器系统;
- 任务之间共享锁、队列、总线等资源,阻塞时间不可忽略;
- 任务本身是并行的(例如一个控制任务内部用多线程/DAG 并行);
- 存在不同等级的关键性(mixed-criticality),有的任务必须“死都不能 miss”,有的偶尔 miss 可以接受;
- 存在 GPU/DSP/NPU 等异构加速器,任务在不同计算单元之间搬运数据,开销不再简单。
从工程实践的角度,可以把 RM/RMA 理解为:
一套“适用于简单单核实时系统的、足够精细但又不至于太复杂”的工具箱。
在这个适用范围内,它非常有价值;但超出这个范围,就要换更复杂的模型和方法了。
7.4 多核、异构、复杂系统:有什么对应的模型和方法?
对于多核、异构、复杂系统,实时系统领域其实已经发展出了不少模型和分析方法,只是复杂度和门槛都比 RM 高得多,这里只做一个鸟瞰:
-
多处理器固定优先级 / EDF 调度:
- 分区式(partitioned)调度:
- 先把任务划分到各个 CPU 核上(类似“装箱问题”),每个核上再分别用单核 RM/EDF 分析;
- 优点是思路清晰,缺点是任务分配本身就是 NP-hard,需要启发式算法或工具辅助。
- 全局式(global)调度:
- 所有任务放在一个全局就绪队列里,由多个核一起从中取任务执行(如 Global EDF、Global RM);
- 有自己的可调度性判据和利用率上界,但比单核 RM 复杂许多,公式门槛较高。
- 分区式(partitioned)调度:
-
考虑共享资源的模型:
- 当任务之间通过互斥锁、队列、总线等共享资源时,需要引入“阻塞时间”的建模;
- 典型方法包括 Priority Ceiling Protocol(PCP)、Stack Resource Policy(SRP)等,它们可以与固定优先级/EDF 调度结合,给出更完整的可调度性分析;
- 在响应时间分析公式中,通常会多出一个“最大阻塞时间”的项。
-
并行/图结构任务模型:
- 对于内部有并行结构的任务(如 DAG 任务、pipeline/graph 型应用),可以使用 DAG 任务模型、同步数据流(SDF)等;
- 分析重点转向“关键路径(critical path)长度 + 总工作量”与多核算力之间的关系;
- 这类模型在信号处理、视频编解码、自动驾驶感知/决策 pipeline 等场景很常见。
-
带宽预留与分层/层级调度(hierarchical scheduling):
- 把复杂系统分解为多个“子系统”,给每个子系统预留一定的 CPU 带宽(如 server 模型、resource reservation);
- 上层用一个“server 任务”代表整个子系统,下层在 server 内部再进行简单的 RM/EDF 调度;
- 这种方式适用于大型平台软件,把不同供应商/模块的资源隔离开来。
-
混合关键性(mixed-criticality)与安全相关系统:
- 在航空、车载等场景,不同任务有不同的安全等级,需要在不同故障模式下保证不同等级的任务;
- 对应有 Mixed-Criticality Scheduling 模型,会给出在“正常模式”和“降级模式”下的不同调度保障;
- 这已经远超出简单 RM 模型的能力范围。
工程上实际常见的做法反而比较“务实”:
- 在一个复杂平台上,尽量为“最关键的一小块”保留一个相对简单、接近单核/固定优先级假设的环境(比如在某个专用核/安全岛上跑 RTOS);
- 在这一小块上使用 RM/RMA 这样的经典模型,得到强实时性保证;
- 对其它非关键部分,使用 CFS、SCHED_DEADLINE 等更灵活的机制,接受“统计意义上的可接受表现”。
换句话说,RM/RMA 虽然源自一个“简陋”的单核模型,但在复杂系统中,它依然扮演着一个用于关键控制环、核心安全功能的“硬实时小岛”分析工具的角色,而整个系统的其他部分则在更复杂、也更灵活的调度框架下运行。
8. 常见调度模型与分析方法一览
为了在工程上快速“选工具”,可以把常见的几类调度模型和分析方法粗略归类如下(只覆盖最常用、能解决 80% 场景的那几种):
| 调度模型 / 策略 | 核心假设(简化版) | 典型分析工具 | 常见工程场景 |
|---|---|---|---|
| 单核 RM(Rate Monotonic) | 单核、抢占式、固定优先级;周期或最小间隔已知; D i = T i D_i = T_i Di=Ti;任务独立、不共享资源 | Liu–Layland 利用率上界;固定优先级响应时间分析(RTA) | MCU+RTOS 控制系统;电机控制、功率变换、传感器采集+控制闭环等“少数几个关键周期任务”的场景 |
| 单核 DM(Deadline Monotonic) | 与 RM 类似,但优先级按相对截止时间长短分配(截短优先) | 与 RM 类似的利用率上界和响应时间分析,只是用 D i D_i Di 替代 T i T_i Ti | 截止时间与周期不同步的场景,如“任务周期是 10 ms,但要求在 5 ms 内完成”的控制/保护逻辑 |
| 单核 EDF(Earliest Deadline First) | 单核、抢占式、动态优先级;总任务利用率 U ≤ 1 U \le 1 U≤1 时在理想假设下可调度 | 需求函数 / demand bound function(dbf);processor demand 分析; U ≤ 1 U \le 1 U≤1 是一个简单必要条件 | 操作系统内核或中间件提供 EDF 调度(如 SCHED_DEADLINE);对截止时间敏感的多媒体、通信、带宽预留场景 |
| 固定优先级 + RTA(响应时间分析) | 单核、抢占式固定优先级;可包含共享资源阻塞时间项 | 经典响应时间迭代公式(第 4 节定理 2),有时附加阻塞项 B i B_i Bi;可以对每个任务给出严格的最坏响应时间 | FreeRTOS / RTX 等 RTOS 中“手工分配优先级”的系统;Linux SCHED_FIFO/SCHED_RR 上少量关键线程的分析 |
| 带共享资源的固定优先级(PCP / SRP 等) | 在固定优先级基础上引入互斥锁、队列等共享资源,任务会被阻塞 | 在响应时间分析中加入阻塞时间 B i B_i Bi;使用 Priority Ceiling Protocol (PCP)、Stack Resource Policy (SRP) 等协议计算 B i B_i Bi 上界 | 有互斥锁保护的控制/通信任务;需要兼顾实时性和数据一致性的嵌入式软件 |
| EDF + 带宽预留(如 Linux SCHED_DEADLINE) | 单核 EDF 调度,每个任务有 ( r u n t i m e , d e a d l i n e , p e r i o d ) (runtime, deadline, period) (runtime,deadline,period) 带宽配置;CBS 等机制保证带宽不被滥用 | EDF 的 dbf/processor-demand 分析;对 server 模型和带宽预留有专门公式 | 多路音视频流、雷达/传感器数据处理 pipeline;需要给不同任务分配精确 CPU 份额的复杂系统 |
| 分区式多核 RM/EDF | 多核;先把任务“装箱”到各个核上,每个核内部再用单核 RM/EDF 分析 | 任务分配阶段使用启发式装箱算法;每个核内部直接用单核 RM/RTA 或 EDF dbf 分析 | 多核 MCU 或 SoC 上,把关键任务分布到不同核:如“一个核做高速控制,一个核做通信”的模式 |
这张表的意图是:当你站在一个具体工程项目面前时,可以先定位自己处在哪个“大类”:
- 如果是单核 MCU + RTOS,任务数量不多,关键任务周期清晰:优先考虑 RM + 利用率上界 + 响应时间分析这一套;
- 如果是在 Linux 上用 SCHED_FIFO/SCHED_RR 跑几个关键线程:本质也是“固定优先级 + 抢占式”,可以用固定优先级 RTA(加上“内核线程/中断”作为额外干扰项)来分析;
- 如果是 Linux SCHED_DEADLINE 或类似 EDF + 带宽预留的机制:更适合用 EDF 及其衍生的 dbf / processor-demand 分析;
- 如果是 多核系统:常见工程做法是“先分区,再在每个核上用单核理论”,而不是一上来就上复杂的全局多处理器理论。
9. 总结
把本文的主要观点压缩成几个工程师可直接记在脑子里的要点,可以是:
-
用 C / T C/T C/T 给每个功能贴上“CPU 占用价签”。
把驱动、控制、通信、日志等都抽象成周期任务,估出每个任务的 C i C_i Ci(最坏执行时间)和 T i T_i Ti(周期/最小间隔),得到 U i = C i / T i U_i=C_i/T_i Ui=Ci/Ti,就能定量回答“这个东西大概吃掉多少 CPU”。 -
用 RMA 的利用率上界做第一道“粗筛”。
对 n n n 个周期任务,如果
U = ∑ C i / T i ≤ n ( 2 1 / n − 1 ) U = \sum C_i/T_i \le n(2^{1/n}-1) U=∑Ci/Ti≤n(21/n−1)
或在任务数较多时近似认为 U ≤ 69.3 % U \le 69.3\% U≤69.3%,则在 RM 下可以认为一定可调度。这是一条简单但相当有用的“总负载安全线”。 -
用响应时间分析对关键任务“逐个过秤”。
当总利用率接近或略高于上界,或者某些任务特别关键时,不再满足于“CPU 大致够用”这种感觉,而是用响应时间迭代表达式把每个关键任务“从被触发到干完”最坏会拖多久算出来,并与其周期/截止时间逐一比较。 -
理解调度策略差异:CFS 讲公平,SCHED_FIFO/SCHED_RR 讲优先级,SCHED_DEADLINE 讲带宽和截止时间。
- CFS 适合通用负载,但基本不给硬实时保证;
- SCHED_FIFO/SCHED_RR 是固定优先级实时类,可以用 RM/RTA 思路分析,区别主要在同级任务是否轮转;
- SCHED_DEADLINE 则是 EDF + 带宽预留阵营,应使用 EDF 对应的分析工具。
-
在多核/复杂系统里,为关键部分保留一个“简单小岛”,在上面用经典模型。
当系统长成“多核 + 异构 + 大量任务”时,与其试图一次性用一个超级模型统一搞定,不如在架构上划出一个相对干净的实时区域(单核或几乎不受干扰的核 + RTOS/实时类),在这块小岛上用 RM/RMA 或 EDF 等经典理论保证硬实时;其他区域则用更灵活的调度策略,接受软实时或统计意义上的保证。 -
让工具(包括 AI)干重复劳动,把脑力用在“建模是否合理”上。
手工算一两组 C / T C/T C/T 还行,几十上百个任务就没必要再手算了。把任务表结构化好( C i , T i C_i,T_i Ci,Ti、优先级、是否关键任务、所属核等),交给脚本或 AI 帮你:
- 批量算利用率并与上界对比;
- 对关键任务迭代响应时间;
- 生成简单的离散时间调度仿真,看看最坏情况下是否会 miss deadline。
这样,当你再遇到“再加一个采样/控制环/协议栈能不能扛?”这类问题时,就不只是凭经验拍脑袋,而是有一整套从模型、公式到仿真的方法论,可以较为系统地支撑你的判断。
10. 参考文献
以下文献均为实时系统调度领域的经典论文、教材或官方文档,按主题分组排列。每条附有 DOI 链接或官方地址,方便查阅原文。
经典理论论文
-
C. L. Liu and J. W. Layland, “Scheduling Algorithms for Multiprogramming in a Hard-Real-Time Environment,” Journal of the ACM, vol. 20, no. 1, pp. 46–61, 1973.
https://doi.org/10.1145/321738.321743
— RM/EDF 理论的奠基论文,给出了利用率上界和最优性证明。 -
J. Y. T. Leung and J. Whitehead, “On the Complexity of Fixed-Priority Scheduling of Periodic, Real-Time Tasks,” Performance Evaluation, vol. 2, no. 4, pp. 237–250, 1982.
https://doi.org/10.1016/0166-5316(82)90024-4
— 证明了固定优先级调度可行性判定的 NP-hard 性质。 -
M. Joseph and P. Pandya, “Finding Response Times in a Real-Time System,” The Computer Journal, vol. 29, no. 5, pp. 390–395, 1986.
https://doi.org/10.1093/comjnl/29.5.390
— 经典的固定优先级响应时间分析(RTA)迭代公式的来源。 -
J. Lehoczky, L. Sha, and Y. Ding, “The Rate Monotonic Scheduling Algorithm: Exact Characterization and Average Case Behavior,” IEEE RTSS, 1989.
https://doi.org/10.1109/REAL.1989.63567
— 对 RM 可调度性的精确刻画及平均情况行为。 -
N. C. Audsley, A. Burns, M. Richardson, K. Tindell, and A. J. Wellings, “Applying New Scheduling Theory to Static Priority Pre-emptive Scheduling,” Software Engineering Journal, vol. 8, no. 5, pp. 284–292, 1993.
https://doi.org/10.1049/sej.1993.0034
— 将响应时间分析系统地应用于工程实际。 -
L. Sha, R. Rajkumar, and J. P. Lehoczky, “Priority Inheritance Protocols: An Approach to Real-Time Synchronization,” IEEE Trans. Computers, vol. 39, no. 9, pp. 1175–1185, 1990.
https://doi.org/10.1109/12.57058
— 优先级继承协议(PIP)和优先级天花板协议(PCP)的原始论文。 -
T. P. Baker, “Stack-Based Scheduling of Realtime Processes,” Real-Time Systems, vol. 3, no. 1, pp. 67–99, 1991.
https://doi.org/10.1007/BF00365393
— Stack Resource Policy(SRP)的原始论文。 -
S. K. Baruah, A. K. Mok, and L. E. Rosier, “Preemptively Scheduling Hard-Real-Time Sporadic Tasks on One Processor,” IEEE RTSS, 1990.
https://doi.org/10.1109/REAL.1990.128746
— sporadic 任务 EDF 可调度性的 demand bound function 分析。 -
S. K. Baruah, R. R. Howell, and L. E. Rosier, “Algorithms and Complexity Concerning the Preemptive Scheduling of Periodic, Real-Time Tasks on One Processor,” Real-Time Systems, vol. 2, no. 4, pp. 301–324, 1990.
https://doi.org/10.1007/BF01995675
— EDF 的 processor demand 分析方法。 -
G. C. Buttazzo, “Rate Monotonic vs. EDF: Judgment Day,” Real-Time Systems, vol. 29, no. 1, pp. 5–26, 2005.
https://doi.org/10.1023/A:1021875921609
— RM 与 EDF 的系统对比,工程上的优劣分析。 -
L. Sha, T. Abdelzaher, K.-E. Årzén, A. Cervin, T. Baker, A. Burns, G. Buttazzo, M. Caccamo, J. Lehoczky, and A. K. Mok, “Real Time Scheduling Theory: A Historical Perspective,” Real-Time Systems, vol. 28, no. 2–3, pp. 101–155, 2004.
https://doi.org/10.1023/B:TIME.0000045315.39789.e4
— 实时调度理论发展史综述,非常适合入门时梳理知识全貌。 -
E. Bini and G. C. Buttazzo, “Schedulability Analysis of Periodic Fixed Priority Systems,” IEEE Trans. Computers, vol. 53, no. 11, pp. 1462–1473, 2004.
https://doi.org/10.1109/TC.2004.103
— 超周期分析与利用率上界的精化。 -
N. C. Audsley, “Optimal Priority Assignment and Feasibility of Static Priority Tasks with Arbitrary Start Times,” Technical Report YCS 164, University of York, 1991.
https://www-users.cs.york.ac.uk/~andy/papers.html
— Audsley 优先级分配算法,用于在固定优先级下寻找可行的优先级排列。
多处理器与全局调度
-
R. I. Davis and A. Burns, “A Survey of Hard Real-Time Scheduling for Multiprocessor Systems,” ACM Computing Surveys, vol. 43, no. 4, article 35, 2011.
https://doi.org/10.1145/1978802.1978814
— 目前最全面的多处理器硬实时调度综述。 -
B. Andersson, S. K. Baruah, and J. Jonsson, “Static-Priority Scheduling on Multiprocessors,” IEEE RTSS, 2001.
https://doi.org/10.1109/REAL.2001.990593
— 全局固定优先级多处理器调度分析。 -
T. P. Baker, “An Analysis of EDF Schedulability on a Multiprocessor,” IEEE Trans. Parallel and Distributed Systems, vol. 16, no. 8, pp. 760–768, 2005.
https://doi.org/10.1109/TPDS.2005.128
— 全局 EDF 多处理器可调度性分析。 -
S. K. Baruah and A. Burns, “Sustainable Schedulability Analysis,” IEEE RTSS, 2006.
https://doi.org/10.1109/RTSS.2006.47
— “sustainable” 可调度性分析框架。
混合关键性与安全相关系统
-
S. Vestal, “Preemptive Scheduling of Multi-Criticality Systems with Varying Degrees of Execution Time Assurance,” IEEE RTSS, 2007.
https://doi.org/10.1109/RTSS.2007.47
— 混合关键性调度的开创性论文。 -
A. Burns and R. I. Davis, “Mixed Criticality Systems — A Review,” 9th edition, University of York, 2022.
https://www-users.cs.york.ac.uk/~burns/review.pdf
— 混合关键性调度领域持续更新的综述,涵盖了绝大部分进展。
带宽预留与层级调度
-
L. Abeni and G. Buttazzo, “Integrating Multimedia Applications in Hard Real-Time Systems,” IEEE RTSS, 1998.
https://doi.org/10.1109/REAL.1998.739726
— Constant Bandwidth Server(CBS)的原始论文,是 Linux SCHED_DEADLINE 的理论基础。 -
I. Shin and I. Lee, “Periodic Resource Model for Compositional Real-Time Guarantees,” IEEE RTSS, 2003.
https://doi.org/10.1109/REAL.2003.1253249
— 层级调度中 periodic resource model 的形式化。 -
J. K. Stankovic, M. Spuri, K. Ramamritham, and G. C. Buttazzo, Deadline Scheduling for Real-Time Systems: EDF and Related Algorithms, Springer, 1998.
https://doi.org/10.1007/978-1-4615-5535-3
— EDF 及其变种的系统化专著。
WCET 分析
- R. Wilhelm et al., “The Worst-Case Execution-Time Problem — Overview of Methods and Survey of Tools,” ACM Trans. Embedded Computing Systems, vol. 7, no. 3, article 36, 2008.
https://doi.org/10.1145/1347375.1347389
— WCET 分析方法和工具链的权威综述。
分布式与网络实时系统
- K. Tindell and J. Clark, “Holistic Schedulability Analysis for Distributed Hard Real-Time Systems,” Microprocessing and Microprogramming, vol. 40, no. 2–3, pp. 117–134, 1994.
https://doi.org/10.1016/0165-6074(94)90067-1
— 分布式实时系统的端到端可调度性分析方法。
教科书与专著
-
Jane W. S. Liu, Real-Time Systems, Prentice Hall, 2000. ISBN 978-0130996510.
— 全面覆盖周期/sporadic 任务模型、RM/DM/EDF、共享资源、多处理器调度。 -
G. C. Buttazzo, Hard Real-Time Computing Systems: Predictable Scheduling Algorithms and Applications, 3rd ed., Springer, 2011.
https://doi.org/10.1007/978-1-4614-0676-1
— 硬实时调度算法、server 模型、资源预留的深入讨论。 -
A. Burns and A. Wellings, Real-Time Systems and Programming Languages, 4th ed., Addison-Wesley, 2009. ISBN 978-0321417459.
— 从编程语言角度看实时系统,覆盖 Ada、Java Real-Time、POSIX。 -
H. Kopetz, Real-Time Systems: Design Principles for Distributed Embedded Applications, 2nd ed., Springer, 2011.
https://doi.org/10.1007/978-1-4419-8237-7
— 偏分布式嵌入式架构设计,TTA 时间触发架构理论。 -
E. A. Lee and S. A. Seshia, Introduction to Embedded Systems: A Cyber-Physical Systems Approach, 2nd ed., MIT Press, 2017.
https://ptolemy.berkeley.edu/books/leeseshia/
— 从 CPS 角度介绍嵌入式系统,包含调度与时间分析基础,电子版免费。
Linux 内核调度相关文档
-
Linux Kernel Documentation — Deadline Task Scheduling (SCHED_DEADLINE).
https://docs.kernel.org/scheduler/sched-deadline.html
— 官方文档,描述 CBS/EDF 在 Linux 中的实现、接口和参数配置。 -
Linux Kernel Documentation — Real-Time Group Scheduling (SCHED_FIFO / SCHED_RR).
https://docs.kernel.org/scheduler/sched-rt-group.html
— 官方文档,描述 RT 调度类的组带宽限制机制。 -
Linux Kernel Documentation — CFS Scheduler Design.
https://docs.kernel.org/scheduler/sched-design-CFS.html
— 官方文档,描述 CFS 的 vruntime 机制与公平性设计。 -
J. Lelli, C. Scordino, L. Abeni, and D. Faggioli, “Deadline Scheduling in the Linux Kernel,” Software: Practice and Experience, vol. 46, no. 6, pp. 821–839, 2016.
https://doi.org/10.1002/spe.2335
— SCHED_DEADLINE 在 Linux 内核中的设计与实现细节。
RTOS 与 MCU 厂商资源
-
FreeRTOS — Official Documentation and API Reference.
https://www.freertos.org/Documentation/
— 最广泛使用的开源 RTOS 之一,官方文档详细说明了固定优先级抢占式调度的行为。 -
STMicroelectronics, “Getting Started with STM32 — General-Purpose Timer Cookbook,” Application Note AN4776.
https://www.st.com/resource/en/application_note/an4776.pdf
— STM32 定时器使用,有助于估算中断和 DMA 处理的 WCET。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)