第三章:PREEMPT_RT补丁应用
说实话,搞实时Linux这么多年,我见过太多人在打补丁这一步翻车了。有的版本没选对,有的补丁冲突不会解,最后内核起不来,一脸懵地来找我。今天咱们就把这块彻底讲透。
3.1 补丁下载与版本匹配
先说说最基础也最关键的事——版本匹配。我刚开始做RT项目时,就吃过这个亏。当时图省事,随便下了个补丁就往内核上打,结果编译报错几百行,排查了整整两天才发现是版本对不上。
PREEMPT_RT补丁的版本号必须和内核源码版本号完全一致。举个例子:
- 内核版本:linux-5.10.100
- 补丁版本:patch-5.10.100-rt58.patch
少一位小数点都不行。5.10.100的补丁不能打在5.10.99上,也不能打在5.10.101上。这是硬性要求。
https://cdn.kernel.org/pub/linux/kernel/projects/rt/。第三方站点下载的补丁,我建议你最好校验一下SHA256。
我个人习惯的做法是,先确定目标内核版本,再去RT补丁目录下找对应的patch文件。目录结构一般是这样的:
rt/
├── 5.10/
│ ├── patch-5.10.100-rt58.patch
│ ├── patch-5.10.100-rt58.patch.sign
│ └── patches/
├── 5.15/
│ ├── patch-5.15.30-rt40.patch
│ └── ...
└── 6.1/
└── ...
你想想看,如果连版本都搞错了,后面所有工作都是白费。所以第一步,请务必确认版本号。
3.2 打补丁流程
版本确认无误后,就可以开始打补丁了。流程其实不复杂,但有几个细节需要注意。
第一步:准备干净的内核源码
我建议从kernel.org下载官方源码,不要用发行版自带的内核。发行版内核往往有额外的修改,容易和RT补丁冲突。
# 下载并解压内核
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.100.tar.xz
tar -xf linux-5.10.100.tar.xz
cd linux-5.10.100
第二步:应用补丁
这里我推荐用 patch 命令的 -p1 参数。为什么是 -p1?因为补丁文件里的路径通常比实际路径多一级目录。
# 应用RT补丁
xzcat ../patch-5.10.100-rt58.patch.xz | patch -p1 --dry-run
# 如果dry-run没有报错,去掉--dry-run正式打补丁
xzcat ../patch-5.10.100-rt58.patch.xz | patch -p1
--dry-run!这步能提前发现99%的问题。我曾经在一个项目里直接打补丁,结果打到一半报错,内核源码目录变得不干不净,最后只能重新解压。从那以后,dry-run成了我的铁律。
第三步:配置内核
补丁打完后,需要开启RT相关的配置选项:
make menuconfig
在 General setup → Preemption Model 中,选择:
Fully Preemptible Kernel (Real-Time)
同时建议检查以下选项是否开启:
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| CONFIG_PREEMPT_RT | y | RT核心功能 |
| CONFIG_HIGH_RES_TIMERS | y | 高精度定时器 |
| CONFIG_NO_HZ_FULL | y | 全无滴答模式 |
| CONFIG_IRQ_FORCED_THREADING | y | 强制中断线程化 |
3.3 补丁冲突解决
嗯,这里要重点说说。补丁冲突是家常便饭,尤其是当你用的内核版本比较新,或者自己改过内核代码。
冲突的表现形式通常是这样的:
Hunk #1 FAILED at 123.
1 out of 1 hunk FAILED
看到这个别慌。我教你一个实用的排查方法:
- 查看reject文件:补丁打失败后,会生成
.rej文件,里面记录了冲突的具体位置。 - 手动合并:打开冲突文件,找到
<<<<<<<标记,手动调整代码。 - 重新验证:修改完后,用
diff命令对比一下,确保修改正确。
我曾经遇到过一个棘手的案例: 客户要在ARM平台上跑RT内核,但他们的BSP里改了中断控制器驱动。RT补丁正好也改了同一部分代码,冲突了二十多处。最后我是一行一行手动合并的,花了整整一个下午。所以我的建议是——尽量用主线内核,少用BSP修改过的版本。
如果冲突实在太多,还有一个办法:换个内核版本。有时候5.10.100的补丁和5.10.99的内核反而能完美匹配,这种事我遇到过不止一次。
3.4 验证RT内核启动
补丁打好了,内核编译通过了,接下来就是验证环节。这一步不能省,我见过有人编译成功就以为万事大吉,结果启动时直接panic。
验证方法一:查看内核启动日志
dmesg | grep -i "preempt"
dmesg | grep -i "rt"
正常启动后,你应该能看到类似这样的输出:
[ 0.000000] Linux version 5.10.100-rt58 (...)
[ 0.000000] Preemptible kernel (with RT)
验证方法二:检查内核配置
cat /proc/config.gz | gunzip | grep PREEMPT_RT
CONFIG_PREEMPT_RT=y
验证方法三:运行cyclictest
这是最直观的测试工具,可以测量内核的实时响应能力:
cyclictest -l 100000 -m -n -p 99
正常RT内核的延迟应该在几十微秒以内。如果看到几百微秒甚至毫秒级的延迟,说明RT配置可能有问题。
maxcpus=1,排除SMP带来的干扰。等确认单核没问题了,再开启多核。
最后说一句,验证RT内核启动,说白了就是确认两件事:一是内核确实跑在了RT模式下,二是实时性能达到了预期。这两个都通过了,才算真正完成了PREEMPT_RT补丁的应用。
整个流程走下来,你会发现其实并不复杂。但每个环节都有坑,版本匹配、补丁冲突、配置遗漏——任何一个出问题,都可能让你白忙活半天。所以我的建议是:慢一点,稳一点,每一步都验证清楚。
总结一下:PREEMPT_RT补丁应用,核心就四步——版本匹配、打补丁、配置、验证。每一步都有坑,但只要你按流程来,多验证,基本不会出大问题。我在多个项目里验证过这套流程,从x86到ARM,从工业控制到音频处理,都跑得很稳。