1. 实时系统概述
1.1 实时系统的定义
实时系统(Real-Time System)是指系统必须在严格的时间约束内对外部事件做出响应的计算系统。其核心特征在于:计算的正确性不仅取决于逻辑结果,还取决于结果产生的时间。如果响应时间超过了规定的截止期限(Deadline),即使逻辑结果正确,系统也被视为失效。
实时系统广泛应用于对时间敏感的领域,例如:
- 航空航天:飞行控制系统、卫星姿态调整
- 工业控制:PLC(可编程逻辑控制器)、机器人运动控制
- 汽车电子:发动机管理、ABS(防抱死制动系统)、ADAS(高级驾驶辅助系统)
- 医疗设备:心脏起搏器、呼吸机、CT扫描仪
- 通信系统:基站信号处理、VoIP(网络电话)
1.2 硬实时与软实时的区别
根据系统对截止期限(Deadline)的违反容忍程度,实时系统可分为硬实时(Hard Real-Time)和软实时(Soft Real-Time)两大类。两者的核心差异在于错过截止期限的后果严重程度。
| 对比维度 | 硬实时(Hard RT) | 软实时(Soft RT) |
|---|---|---|
| 错过Deadline的后果 | 系统灾难性失效,可能导致人员伤亡或设备损毁 | 系统性能下降,但不会造成灾难性后果 |
| 时间确定性要求 | 必须100%保证在最坏情况下仍满足时间约束 | 允许偶尔超时,统计上满足即可 |
| 典型应用 | 飞行控制、核反应堆安全系统、心脏起搏器 | 视频播放、VoIP、在线游戏、数据采集 |
| 调度策略 | 优先级驱动的抢占式调度(如RMS、EDF) | 优先级调度 + 尽力而为 |
| 验证方式 | 形式化验证、最坏情况执行时间(WCET)分析 | 统计测试、平均性能评估 |
1.3 Linux 实时性面临的挑战
Linux 最初设计为通用分时操作系统,其核心调度策略追求公平性和吞吐量最大化,而非严格的时间确定性。这使得原生 Linux 内核在实时场景下面临以下关键挑战:
1.3.1 内核抢占点过多
在标准 Linux 内核中,当进程执行系统调用进入内核态后,大部分内核代码是不可抢占的。这意味着即使一个高优先级实时任务就绪,也必须等待当前在内核中执行的进程主动释放 CPU(如返回用户态或主动调度),才能获得执行权。这种不可抢占的临界区长度不确定,导致实时任务的响应延迟不可预测。
1.3.2 中断处理延迟
Linux 的中断处理分为上半部(Top Half)和下半部(Bottom Half)。上半部在中断上下文中执行,会禁止本地 CPU 中断,导致其他中断无法响应。下半部(如 Softirq、Tasklet、Workqueue)虽然可以延迟处理,但其调度优先级和抢占行为复杂,增加了时间不确定性。
1.3.3 自旋锁与优先级反转
内核中广泛使用自旋锁(Spinlock)保护共享资源。当低优先级任务持有自旋锁时,高优先级任务如果尝试获取同一锁,只能忙等待(自旋),导致高优先级任务被低优先级任务阻塞,形成优先级反转问题。标准 Linux 虽然实现了优先级继承协议(Priority Inheritance),但在复杂场景下仍存在延迟抖动。
1.3.4 时钟粒度与定时器精度
标准 Linux 内核的时钟中断周期通常为 1ms(1000Hz)或 4ms(250Hz),定时器精度受限于此。对于需要微秒级或亚微秒级定时精度的实时应用,原生内核的定时器分辨率远远不够。
1.4 PREEMPT_RT 的解决思路
为了应对上述挑战,Linux 社区开发了 PREEMPT_RT(Real-Time Linux) 补丁集。其核心思路是通过一系列内核改造,将 Linux 转变为完全可抢占的实时操作系统。主要改造方向包括:
- 完全内核抢占:通过将自旋锁替换为可睡眠的互斥锁(rtmutex),使内核中几乎所有位置都可被抢占,大幅缩短不可抢占临界区。
- 中断线程化:将中断处理程序的上半部也放入可被调度的内核线程中执行,降低中断关闭时间,使高优先级实时任务可以抢占中断处理。
- 高精度定时器:引入高精度定时器(hrtimer)框架,提供纳秒级的定时精度,替代传统的基于 jiffies 的定时器。
- 优先级继承优化:完善 rtmutex 的优先级继承协议,有效避免优先级反转问题。