实时操作系统如何能够做到实时?

实时操作系统之所以能“实时”,核心并不是它平均运行得更快,而是它能尽量保证:

某个关键任务在规定的最迟时间之前,一定得到 CPU 并完成处理。

换句话说,实时系统最重要的是确定性(determinism),而不是单纯的速度。

例如,假设一个电机控制任务要求每 1 ms 执行一次。普通 Linux/Windows 可能大多数时候都能在 1 ms 内执行,但偶尔因为后台任务、内存换页、驱动程序、系统中断等原因拖到 5 ms、20 ms。对于普通电脑,这只是“卡了一下”;但对飞行控制、汽车制动、工业控制、火星车姿态控制来说,这可能就是故障。

RTOS 会通过一整套机制,把这种“偶尔卡住”的不确定性压到很低。

最关键的一点是基于优先级的抢占式调度

假设系统里有三个任务:

  • A:姿态控制,优先级最高
  • B:通信
  • C:日志记录,优先级最低

如果 CPU 正在执行日志任务 C,这时姿态控制任务 A 到期了,RTOS 不会等 C 做完,而是立即暂停 C,把 CPU 交给 A。

这叫:

Preemptive Scheduling,抢占式调度。

因此,高优先级任务的响应时间可以比较精确地估算。

可以简单理解为:

普通桌面系统:

任务A ────────┐
后台程序 ─────────────
磁盘访问 ─────────
驱动程序 ───────
任务B ─────────────

什么时候轮到关键任务?
大多数时候很快,但不保证。


RTOS:

低优先级任务 ───────┐
                    ↓ 被抢占
高优先级任务        █████████
                    ↑ 立即执行
低优先级任务              └────继续执行

第二个关键机制是中断响应时间必须可控

比如一个传感器突然产生中断:

“新的姿态数据到了。”

CPU 从当前任务转去执行中断服务程序,需要一定时间,这叫:

Interrupt Latency,中断延迟。

普通操作系统可能出现:

10 μs
20 μs
15 μs
突然一次 2 ms

平均值看起来不错,但对于实时控制,最后那个 2 ms 可能不可接受。

RTOS 更关注的是:

最坏情况下最多延迟多少?

比如系统设计目标可能是:

中断延迟 < 10 μs
任务切换 < 5 μs

只要这些上限是可以分析和验证的,工程师就可以设计整个控制系统。

所以实时系统里经常关心一个概念:

Worst-Case Execution Time,WCET,最坏执行时间。

这也是 RTOS 和普通操作系统思维方式的一个重要区别。

普通系统更关注:

平均性能是多少?

实时系统更关注:

最差情况下会不会超时?

第三个重要机制是避免不可预测的系统行为

例如桌面操作系统常常使用虚拟内存。如果 RAM 不够,系统可能把一部分数据交换到磁盘:

RAM
 ↓
Page Fault
 ↓
SSD / 硬盘
 ↓
重新加载

这次访问可能原本只需要几十纳秒,却突然变成几百微秒甚至几毫秒。

这种行为对于实时系统非常麻烦。

所以很多 RTOS:

不使用分页,或者严格限制动态内存操作。

类似的问题还包括垃圾回收。

一些高级语言运行时可能突然进行:

Garbage Collection

于是程序停顿几十毫秒。

对于网页服务器可能没有问题,但对于 1 kHz 的飞控循环就可能完全不能接受。

因此高等级实时系统通常尽量避免:

  • 不可预测的内存分配
  • 页面交换
  • 长时间垃圾回收
  • 不确定的磁盘访问
  • 不受控制的后台进程

第四个关键机制是高精度定时器

RTOS 中的很多任务不是“有空就运行”,而是按照严格周期执行。

例如:

姿态控制:        每 1 ms
电机控制:        每 2 ms
传感器融合:      每 5 ms
导航算法:        每 20 ms
通信:            每 100 ms
日志:            每 1 s

RTOS 的硬件定时器到点以后会产生中断,然后调度相应任务。

于是形成非常稳定的控制周期:

0 ms    控制
1 ms    控制
2 ms    控制
3 ms    控制
4 ms    控制
...

这对控制系统尤其重要。

例如 PID 控制器假定采样周期为:

Ts = 1 ms

如果实际变成:

1.0 ms
1.1 ms
0.9 ms
5.4 ms
0.8 ms

控制效果可能明显恶化。

这种周期执行时间的波动叫:

Jitter,抖动。

RTOS 的一个重要目标,就是让 jitter 尽可能小。

还有一个很容易被忽略的问题叫优先级反转

假设:

  • 高优先级任务 A
  • 中优先级任务 B
  • 低优先级任务 C

低优先级 C 先锁住一个共享资源:

Mutex

这时高优先级 A 也需要这个资源,于是只能等 C。

偏偏中优先级 B 又抢占 C。

于是形成:

A 等 C
C 又被 B 抢占

结果本来最高优先级的 A,反而被间接拖延。

这就是:

Priority Inversion,优先级反转。

著名的 Mars Pathfinder 任务就曾出现过类似的优先级反转问题,最终通过 VxWorks 的优先级继承机制解决。

原理是:

如果 C 挡住了最高优先级 A,那么临时把 C 的优先级提升到 A 的级别:

C 原本优先级:低
        ↓
A 等待 C
        ↓
C 临时获得高优先级
        ↓
C 快速完成
        ↓
释放锁
        ↓
A 运行

这叫:

Priority Inheritance,优先级继承。

现代 RTOS 中还有:

Priority Ceiling,优先级天花板

等机制,专门解决类似问题。

所以,如果把 RTOS 为什么“实时”压缩成一句话,就是:

通过可预测的调度、中断、内存和资源管理,把关键任务的最坏响应时间控制在一个可以计算和验证的范围内。

可以把普通操作系统和 RTOS 简化对比如下:

特性Windows / 普通 LinuxRTOS
核心目标吞吐量、体验确定性
调度公平、综合优化严格优先级
关键任务抢占不一定严格强调及时抢占
中断延迟可能波动较大有严格上限
调度延迟不容易保证可分析
虚拟内存大量使用常限制或不用
页面交换常见通常避免
Jitter可以较大尽量小
WCET通常不关注非常重要
典型应用PC、服务器飞控、汽车、工业控制、航天

还要特别强调:

实时 ≠ 快。

例如两个系统:

系统 A:

平均响应:0.1 ms
最坏响应:50 ms

系统 B:

平均响应:0.8 ms
最坏响应:1.0 ms

如果任务要求:

Deadline = 2 ms

那么 B 才是真正适合实时控制的系统。

虽然 A 平均快了 8 倍,但它偶尔会出现 50 ms 的延迟,所以不能保证任务按时完成。

这也正是为什么火星车会选择 VxWorks 这样的 RTOS。对于毅力号来说,RAD750 的算力和今天的手机相比非常低,但 NASA 更关心的是:

“什么时候执行,我知道;最迟什么时候完成,我也知道。”

而不是单纯追求:

“平均跑得有多快。”

这其实就是实时操作系统最本质的设计哲学:不是追求最快,而是追求可预测。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

Are you human? Please solve:Captcha