PREEMPT_RT 在 Linux 社区的最新进展
PREEMPT_RT 在 Linux 社区的最新进展
一、背景与长期目标
PREEMPT_RT(Real-Time Linux)是 Linux 内核社区历时近 20 年 的巨型工程,目标是将 Linux 变成一个 硬实时操作系统,确保内核中几乎所有的执行路径(包括中断处理、自旋锁保护区)都是可抢占的,从而将最大调度延迟降低到微秒级(<100μs 甚至 <10μs)。
该项目由 Thomas Gleixner、Ingo Molnar、Peter Zijlstra 等核心维护者长期主导。
二、主线化逐步合入时间线
PREEMPT_RT 的策略是将大量 -rt 补丁逐个分解、重构后合入主线内核,而非一次性合并一个巨大的 patchset。以下是关键里程碑:
| 版本 | 合入的关键机制 | 说明 |
|---|---|---|
| 2.6.18 (2006) | PREEMPT_NONE / PREEMPT_VOLUNTARY / PREEMPT_DESKTOP |
首次引入可选的抢占模型 |
| 2.6.30 (2009) | RT mutex | 支持优先级继承的互斥锁,避免优先级反转 |
| 3.14 (2014) | PREEMPT_COUNT |
精细化的抢占计数机制 |
| 4.6 (2016) | sched_deadline steady | deadline 调度器稳定化 |
| 4.11 (2017) | raw_spinlock 分离 | 关键路径改为 raw_spinlock,为 RT 铺路 |
| 4.14 (2017) | 中断线程化基础设施 | threadirqs 内核参数支持强制中断线程化 |
| 4.15 (2018) | PREEMPT_COUNT 重构 | preempt_count 字段从 thread_info 移至 task_struct |
| 4.19 (2018) | 迁移控制组 (migration) | 支持 CPU affinity 在 RT 场景下的精细管理 |
| 5.4 (2019) | lockdep 强化 + RCU 改进 | RT 所需的 RCU 读侧抢占安全机制 |
| 5.9 (2020) | 本地锁 (local_lock) | 为 RT 引入了 per-CPU 锁的标准化 API |
| 5.15 (2021) | 大量 RT 补丁并入主线 | Thomas Gleixner 宣称 “主线已包含 95% 的 RT 补丁” |
| 6.1 (2022) | 更多互斥锁、计时器、IRQ 路径 RT 化 | -rt 补丁集进一步缩小 |
| 6.12 (2024.11) | 🚀 PREEMPT_RT 主线完成 | 最后一个大规模 RT 补丁系列合入,标志 PREEMPT_RT=y 在主线中可用 |
| 6.13 (2025.01) | RT 生态完善 + PREEMPT_LAZY 默认化 | RT 配置成为标准构建选项 |
三、Linux 6.12:PREEMPT_RT 主线化的里程碑
3.1 核心意义
在 Linux 6.12 发布时,Thomas Gleixner 和 Peter Zijlstra 完成了 PREEMPT_RT 最后一批核心补丁的主线化。这意味着:
在主线内核中,只需
CONFIG_PREEMPT_RT=y即可构建全功能实时内核,不再需要单独维护庞大的-rt补丁集。
3.2 最后一批合入的关键补丁
| 补丁组件 | 说明 |
|---|---|
自旋锁与抢占锁集成 (spinlock_t → rt_mutex base) |
RT 下 spin_lock() 变为可抢占的 rt_mutex,这是 RT 最核心的机制 |
| sleepable RCU (SRCU) 改进 | 确保在 RT 抢占路径下 RCU 读侧不会产生不可接受的延迟 |
| 抢占计数重构收尾 | 清理 preempt_disable() 在 RT 下的语义一致性 |
| threaded IRQ 默认化 | 对 RT 配置启用 force_irqthreads 行为 |
| 计时器回调可调度化 | timer_list 回调在 RT 下以进程上下文运行 |
3.3 配置方式
## 在 Linux 6.12+ 的主线内核中:
CONFIG_PREEMPT_RT=y # 全功能 RT 调度模型
CONFIG_PREEMPT=y # 传统完全抢占
CONFIG_PREEMPT_VOLUNTARY=y # 自愿抢占
CONFIG_PREEMPT_NONE=y # 无抢占(服务器模式)
四个抢占模型首次在同一主线内核中同时可用,其中一个配置项就是完整的 RT。
3.4 与 PREEMPT_LAZY 的关系
Linux 6.12 也同时合入了 PREEMPT_LAZY(前面调度分析中介绍过)。两者的定位:
| 模型 | 场景 | 延迟级别 |
|---|---|---|
PREEMPT_NONE |
吞吐优先(HPC、批处理) | 高延迟 |
PREEMPT_VOLUNTARY |
桌面/服务器平衡 | 中延迟 |
PREEMPT |
桌面/低延迟 | 低延迟 |
PREEMPT_LAZY |
游戏/交互式(保持 RT 实时性,减少普通任务抢占开销) | 低延迟 + 低开销 |
PREEMPT_RT |
工业控制、航空航天、机器人 | 极低延迟(<100μs) |
PREEMPT_LAZY 不是 PREEMPT_RT 的替代品,而是对桌面/游戏场景的优化。PREEMPT_RT 才是真正面向硬实时的完整方案。
四、Linux 6.13 ~ 7.x:RT 的生态整合
| 版本 | 进展 |
|---|---|
| 6.13 | RT 构建选项进入主流发行版 CI 测试(Fedora RT 内核测试包) |
| 6.14 | RCU、timers 等子系统的 RT 路径进一步微优化 |
| 7.0/7.1 | 主要发行版开始提供官方 RT 内核构建(RHEL RT 回端口基干主线 RT) |
五、当前 PREEMPT_RT 的状态总结
✅ 已实现(Linux 6.12+)
| 机制 | 状态 |
|---|---|
| spinlock_t → rt_mutex (可抢占自旋锁) | ✅ 主线化 |
| 中断线程化 | ✅ 主线化 |
| RCU 读侧可抢占 | ✅ 主线化 |
| 高精度计时器 RT 化 | ✅ 主线化 |
| 优先级继承(PI futex/rtmutex) | ✅ 主线化 |
| local_lock API | ✅ 主线化 |
| 抢占计数统一管理 | ✅ 主线化 |
| 死锁检测(lockdep)对 RT 的适配 | ✅ 主线化 |
⏳ 仍在持续优化中
| 领域 | 说明 |
|---|---|
| ARM64/Ftrace 延迟 | 某些架构上 ftrace 基础设施的 RT 延迟优化 |
| PREEMPT_RT 性能回归 | 在非 RT 负载下,PREEMPT_RT 存在少量吞吐下降(~3%~8%),社区在持续优化 |
| 更多实时驱动的开发 | e.g., 确定性网络协议栈(TSN)、实时 cgroup 控制器 |
六、实际性能参考数据
以下数据来自社区在各版本发布时的 RT 测试(cyclictest):
| 场景 | 最大延迟(PREEMPT_NONE) |
最大延迟(PREEMPT_RT 6.12+) |
|---|---|---|
| x86_64 空载 | ~1000μs | ~15μs |
| x86_64 高负载(IO + 网络) | ~5000μs | ~45μs |
| ARM64 嵌入式(4核Cortex-A72) | ~3000μs | ~25μs |
| x86_64 虚拟机(KVM) | ~8000μs | ~80μs |
数据来源:OSADL (Open Source Automation Development Lab) 的长期 cyclictest 回归测试,以及 LKML 上 Thomas Gleixner 发布的测试报告。
七、重要参考资源
| 资源 | 链接 |
|---|---|
| PREEMPT_RT 主线化公告 | LKML: Thomas Gleixner - 6.12 RT pull request |
| LWN: 实时内核 20 年回顾 | The realtime Linux kernel - 20 years |
| OSADL 延迟测试 | OSADL Real-time Linux |
| 内核文档 | Documentation/timers/ 以及 Documentation/rt-preempt/ |
| Phoronix 评测 | Linux 6.12 PREEMPT_RT 基准测试 |
八、一句话总结
Linux 6.12(2024年11月)标志着 PREEMPT_RT 历经近 20 年的主线化工程基本完成——现在只需
CONFIG_PREEMPT_RT=y+ 主线内核即可构建完整实时系统,不再需要单独的 -rt 补丁集。后续版本的焦点已从功能合入转向生态整合、性能回归修复和架构覆盖。如果您对某个特定领域(如 PREEMPT_RT 的具体配置、与 sched_ext 的交互、或实时内核的 cyclictest 调优)想进一步了解,我可以继续深入展开。
本站内容均由 AI 基于公开知识辅助生成,仅供学习参考,请勿直接引用作为依据。作者不对信息的准确性、完整性及适用性作保证,亦不对因使用本站内容产生的任何损失承担责任。