4、PREEMPT_RT内核编译与部署:获取源码、配置内核选项、编译与安装、启动验证

好,咱们进入正题。这一章讲的是PREEMPT_RT内核的编译与部署。说白了,就是怎么把那个“实时补丁”打到内核里,然后编译、装上去,最后验证它到底能不能跑出实时效果。

我刚开始接触这块的时候,也踩过不少坑。比如编译完了启动直接panic,或者跑起来发现延迟比标准内核还高……嗯,这些我都会在下面提到。你跟着我的步骤走,能省不少时间。

4.1 获取源码:从哪里下载?

首先,你得拿到两样东西:标准内核源码PREEMPT_RT补丁。这两者版本必须严格对应,差一个patch level都不行。

  • 标准内核源码:去 kernel.org 下载。我个人习惯用长期支持版(LTS),比如5.10.y或5.15.y。稳定,社区支持好。
  • PREEMPT_RT补丁:去 rt.wiki.kernel.org 找。页面里有个“Patch”列表,找到对应你内核版本的 .patch.xz 文件。
我的经验:千万别用最新的主线内核打RT补丁。主线变动太快,补丁可能还没跟上。我遇到过一回,编译倒是过了,但跑起来调度器行为异常。后来老老实实换回LTS版本,一次搞定。

下载命令示例:

# 下载内核源码
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.145.tar.xz

# 下载RT补丁
wget https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.15/older/patch-5.15.145-rt83.patch.xz

# 解压
tar -xf linux-5.15.145.tar.xz
cd linux-5.15.145

# 打补丁
xzcat ../patch-5.15.145-rt83.patch.xz | patch -p1

打完补丁后,源码目录里会多出一些RT相关的文件。你可以用 git diff 看看改动量,通常有几百个文件被修改。嗯,这很正常。

4.2 配置内核选项:打开实时开关

源码准备好了,接下来就是配置。这一步最关键,也最容易漏东西。

我建议你基于现有的配置文件来改。比如从 /boot/config-$(uname -r) 复制一份过来,然后运行 make menuconfig

你需要手动开启以下几个关键选项:

配置项 路径 说明
CONFIG_PREEMPT_RT_FULL General setup → Preemption Model 选择“Fully Preemptible Kernel (RT)”
CONFIG_HIGH_RES_TIMERS General setup → Timers subsystem 高精度定时器,RT必备
CONFIG_NO_HZ_FULL General setup → Timers subsystem 减少定时器中断干扰,建议开启
CONFIG_IRQ_FORCED_THREADING Kernel Features → IRQ subsystem 强制中断线程化,减少关中断时间
注意:如果你用的是ARM或ARM64平台,还要检查 CONFIG_ARM_GICCONFIG_ARM_ARCH_TIMER 是否开启。我曾经在树莓派上忘了开GIC中断控制器支持,结果系统响应延迟直接飙到毫秒级,排查了两天才发现。

配置完成后,保存退出。你可以用 grep PREEMPT .config 确认一下:

grep PREEMPT .config
# 应该看到:
# CONFIG_PREEMPT_RT_FULL=y
# CONFIG_PREEMPT_RT=y

4.3 编译与安装:耐心等待

配置好了,开始编译。这里我建议你用多核编译,能快不少。

# 编译内核和模块
make -j$(nproc) bzImage
make -j$(nproc) modules

# 安装模块
sudo make modules_install

# 安装内核
sudo make install

编译时间取决于你的机器。我自己的笔记本(8核)编译5.15内核大概需要15分钟。如果你用的是嵌入式开发板交叉编译,那时间会更长,建议用 distccccache 加速。

一个小技巧:编译前先运行 make olddefconfig,它会自动把新选项设为默认值。这样你只需要手动改那几个RT相关的选项,省事很多。

安装完成后,检查一下 /boot 目录:

ls /boot/vmlinuz-*
# 应该能看到类似 vmlinuz-5.15.145-rt83 的文件

4.4 启动验证:到底有没有生效?

重启系统,在GRUB菜单里选择新内核启动。如果GRUB没自动识别,你可以手动更新:

sudo update-grub

启动后,第一件事就是确认内核版本:

uname -a
# 输出应该包含 "PREEMPT RT" 字样
# 例如:Linux host 5.15.145-rt83 #1 SMP PREEMPT_RT ...

如果看到 PREEMPT_RT,说明补丁生效了。但光看这个还不够,你得实际测一下实时性能。

我常用的测试工具是 cyclictest(来自rt-tests包):

# 安装rt-tests
sudo apt install rt-tests

# 运行测试,测量1000次,间隔1000微秒
sudo cyclictest -l 1000 -m -n -p 99 -i 1000 -h 100

输出结果里,重点关注 最大延迟(Max Latency)。在标准内核上,这个值可能几百微秒甚至几毫秒。在PREEMPT_RT内核上,通常能控制在50微秒以内。我自己的测试环境(x86_64)跑出来最大延迟是23微秒,嗯,这个水平对于大多数工业控制场景已经够用了。

避坑指南:如果你发现最大延迟还是很高(比如超过200微秒),别急着怀疑内核。先检查一下:

  • BIOS里有没有关闭CPU调频、C-State省电模式?
  • 有没有其他高优先级中断在干扰?比如网卡、显卡。
  • 你的测试程序本身有没有被调度到同一个CPU核心上?

我曾经在笔记本上测,最大延迟一直下不来,后来发现是ACPI的省电策略在捣鬼。关掉之后,延迟直接降了一个数量级。

4.5 知识体系总览

下面这张图,我把整个流程串起来了。你对照着看,心里就有数了。

PREEMPT_RT 内核编译与部署流程 获取源码 kernel.org + RT补丁 配置内核 menuconfig / olddefconfig 编译安装 make -j$(nproc) 启动验证 uname -a / cyclictest 关键配置项(必须开启) CONFIG_PREEMPT_RT_FULL 完全可抢占内核 CONFIG_HIGH_RES_TIMERS 高精度定时器 CONFIG_IRQ_FORCED_THREADING 强制中断线程化 验证成功标志 uname -a 显示 PREEMPT_RT cyclictest 最大延迟 < 50μs

这张图把四个步骤串起来了:获取源码 → 配置内核 → 编译安装 → 启动验证。每个环节都有对应的关键动作和检查点。你照着这个流程走,基本不会出大问题。

好了,这一章的内容就到这里。PREEMPT_RT内核的编译部署,说白了就是“打补丁、开选项、编译、测试”这四步。每一步都有坑,但只要你细心对照我上面说的检查点,应该能顺利搞定。


专注资料整理