一、实时系统:不只是快,更是确定性
大家好,我是你们的老朋友。今天咱们聊聊实时调度。
很多人一听到「实时」,第一反应就是「快」。其实不然。实时系统的核心不是快,而是确定性——你得保证任务在某个时间点之前必须完成。晚了一毫秒,可能就是灾难。
我早年做过一个工业控制项目,机械臂的抓取动作必须在 10ms 内响应。有一次因为调度器没处理好,响应延迟到了 12ms,结果机械臂直接撞上了工件。嗯,那次教训让我深刻理解了「实时」二字的重量。
1.1 硬实时 vs 软实时
实时系统分两类,区别在于错过截止时间的后果。
| 类型 | 错过截止时间 | 典型场景 |
|---|---|---|
| 硬实时 | 系统崩溃或灾难 | 飞行控制、汽车安全气囊、心脏起搏器 |
| 软实时 | 性能下降,但能接受 | 视频播放、在线游戏、语音通话 |
硬实时系统,说白了就是「死线」——过了就是过了,没有商量余地。我见过一个航空电子系统的设计文档,里面明确写着:「任何任务超过截止时间,视为系统失效。」
软实时就宽容多了。你看视频时偶尔卡顿一下,虽然不爽,但不会出人命。不过,软实时也有自己的底线——丢帧率不能超过某个阈值,否则用户体验就崩了。
1.2 调度算法分类:从简单到复杂
调度算法,说白了就是「谁先干活」的问题。咱们从最基础的开始聊。
FCFS(先来先服务)
最简单,也最原始。谁先到,谁先执行。就像排队买奶茶。
但问题很明显:如果一个长任务先来了,后面所有短任务都得等着。这就是所谓的「护航效应」。我在一个日志处理系统中见过这种场景——一个大文件解析任务堵住了后面所有的小查询,用户直接投诉系统「卡死了」。
SJF(短作业优先)
顾名思义,谁短谁先跑。听起来很合理对吧?但有个致命问题:你事先不知道任务到底要跑多久。而且,如果短任务源源不断,长任务可能永远得不到执行——这叫「饥饿」。
RR(时间片轮转)
每个任务分一个时间片,轮流执行。公平,但上下文切换开销大。
时间片选多大?这是个艺术。太短,切换开销吃掉 CPU;太长,又退化成 FCFS。我个人习惯:对于实时系统,时间片通常设在 1ms~10ms 之间,具体看任务粒度。
优先级调度
给每个任务一个优先级,高优先级的先跑。听起来完美,但有两个坑:
- 优先级反转:低优先级任务拿着锁,高优先级任务等它释放。我见过一个惨案——三个任务互相等锁,系统直接死锁。
- 饥饿:低优先级任务永远得不到 CPU。
解决方案?优先级继承协议。嗯,这个后面章节会细讲。
二、实时调度策略:RMS 与 EDF
上面那些是通用调度算法。实时系统有自己专用的调度策略,最经典的两个:RMS 和 EDF。
2.1 RMS(速率单调调度)
RMS 的核心思想:周期越短的任务,优先级越高。为什么?因为周期短意味着截止时间更紧迫。
举个例子:
- 任务 A:周期 10ms,执行时间 3ms
- 任务 B:周期 20ms,执行时间 5ms
RMS 会给 A 更高优先级,因为它的周期更短。
RMS 有个著名的可调度性判定公式:
U = Σ (Ci / Ti) ≤ n * (2^(1/n) - 1)
其中 U 是 CPU 利用率,Ci 是执行时间,Ti 是周期,n 是任务数。
当 n 很大时,这个上限趋近于 ln2 ≈ 0.693。也就是说,RMS 最多只能利用 69.3% 的 CPU。超过这个值,就可能出现任务错过截止时间。
2.2 EDF(最早截止时间优先)
EDF 更直观:谁先到截止时间,谁先执行。它不关心周期长短,只看「死线」远近。
EDF 的可调度性判定很简单:
U = Σ (Ci / Ti) ≤ 1
理论上,EDF 可以 100% 利用 CPU。但实际中,我很少见到有人敢跑到 90% 以上——因为一旦过载,EDF 会「多米诺骨牌」式地错过所有截止时间,这叫「多米诺效应」。
RMS 在过载时表现更优雅——低优先级任务先挂,高优先级任务还能撑住。EDF 则是大家一起完蛋。
| 特性 | RMS | EDF |
|---|---|---|
| 优先级分配 | 静态(周期越短越高) | 动态(截止时间越近越高) |
| CPU 利用率上限 | ≈ 69.3%(n→∞) | 100%(理论) |
| 过载行为 | 低优先级任务先失败 | 所有任务可能一起失败 |
| 实现复杂度 | 低(固定优先级) | 高(需要动态排序) |
三、知识体系总览
下面这张图,是我自己梳理的实时调度知识结构。你把它存下来,后面学起来会清晰很多。
四、总结与避坑
好了,咱们把这一章的核心点捋一捋:
- 实时 ≠ 快,而是确定性。记住这个,你就入门了。
- 硬实时:错过截止时间 = 灾难。软实时:错过可以接受,但别太过分。
- FCFS、SJF、RR、优先级:通用调度算法,各有各的坑。优先级反转和饥饿是常见问题。
- RMS:静态优先级,简单可靠,但 CPU 利用率上限低。
- EDF:动态优先级,利用率高,但过载时容易崩盘。
嗯,这一章就到这里。实时调度是个大话题,后面咱们会深入聊优先级反转、锁机制、多核调度这些硬核内容。慢慢来,不着急。