第三章: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 setupPreemption 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

看到这个别慌。我教你一个实用的排查方法:

  1. 查看reject文件:补丁打失败后,会生成 .rej 文件,里面记录了冲突的具体位置。
  2. 手动合并:打开冲突文件,找到 <<<<<<< 标记,手动调整代码。
  3. 重新验证:修改完后,用 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配置可能有问题。

💡 我的经验: 第一次启动RT内核时,建议先用单核模式测试。在grub启动参数里加 maxcpus=1,排除SMP带来的干扰。等确认单核没问题了,再开启多核。

最后说一句,验证RT内核启动,说白了就是确认两件事:一是内核确实跑在了RT模式下,二是实时性能达到了预期。这两个都通过了,才算真正完成了PREEMPT_RT补丁的应用。

整个流程走下来,你会发现其实并不复杂。但每个环节都有坑,版本匹配、补丁冲突、配置遗漏——任何一个出问题,都可能让你白忙活半天。所以我的建议是:慢一点,稳一点,每一步都验证清楚。

PREEMPT_RT补丁应用流程 1. 版本匹配 内核版本 == 补丁版本 2. 打补丁 patch -p1 --dry-run 3. 配置内核 开启PREEMPT_RT 有冲突? 冲突解决 手动合并.rej文件 重新打补丁 4. 编译内核 make -j$(nproc) 5. 验证RT内核启动 dmesg | cyclictest | /proc/config.gz 关键点:版本精确匹配 → dry-run预检 → 冲突手动解决 → 多维度验证

总结一下:PREEMPT_RT补丁应用,核心就四步——版本匹配、打补丁、配置、验证。每一步都有坑,但只要你按流程来,多验证,基本不会出大问题。我在多个项目里验证过这套流程,从x86到ARM,从工业控制到音频处理,都跑得很稳。

专注资料整理