4. PREEMPT_RT内核配置
构建实时 Linux 系统的第一步是获取正确的内核源码并应用 PREEMPT_RT 补丁。本章将详细讲解从源码获取、补丁应用到内核配置选项的完整流程,重点剖析 PREEMPT_RT_FULL 等关键配置项,帮助您搭建一个可运行高精度定时器驱动的实时内核环境。
前置提醒: 建议使用长期支持(LTS)版本的内核,因为 RT 补丁通常优先支持 LTS 分支。请确认所选内核版本与 RT 补丁版本严格匹配,否则可能导致编译失败或运行时异常。
4.1 内核源码获取与 RT 补丁应用
4.1.1 获取内核源码
从 kernel.org 获取主线内核源码,推荐使用 LTS 版本。以下以 Linux 6.1 LTS 为例:
# 下载内核源码
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.38.tar.xz
# 解压
tar -xf linux-6.1.38.tar.xz
cd linux-6.1.38
4.1.2 下载并应用 PREEMPT_RT 补丁
RT 补丁由内核实时维护团队发布,可从 kernel.org/pub/linux/kernel/projects/rt/ 获取。补丁版本必须与内核版本完全一致。
# 下载对应版本的 RT 补丁
wget https://cdn.kernel.org/pub/linux/kernel/projects/rt/6.1/patch-6.1.38-rt13.patch.xz
# 解压补丁
xz -d patch-6.1.38-rt13.patch.xz
# 应用补丁(位于内核源码根目录)
patch -p1 < patch-6.1.38-rt13.patch
常见错误: 如果补丁应用过程中出现“Hunk #1 FAILED”等错误,说明内核版本与补丁版本不匹配。请使用
uname -r 检查当前内核版本,并下载完全对应的 RT 补丁。
4.1.3 补丁应用验证
补丁应用成功后,可通过以下方式验证:
- 查看版本号: 执行
make kernelversion,输出应包含-rt后缀,如6.1.38-rt13。 - 检查文件变更: 使用
git diff --stat(如果内核目录已初始化为 git 仓库)查看修改的文件列表,RT 补丁通常会修改数百个文件。 - 确认关键文件: 检查
kernel/sched/目录下是否存在rt.c、deadline.c等实时调度相关文件。
最佳实践: 建议在应用补丁前使用
git init && git add . && git commit -m "base kernel" 创建初始提交,这样补丁应用后可通过 git diff 清晰查看所有变更,也便于后续回退。
4.2 内核配置选项详解
应用 RT 补丁后,内核会新增一系列实时相关的配置选项。正确配置这些选项是发挥 PREEMPT_RT 性能的关键。
4.2.1 进入配置界面
# 使用 menuconfig 进行配置
make menuconfig
在配置界面中,RT 相关选项主要分布在 General Setup → Preemption Model 和 Kernel Features 等菜单下。
4.2.2 抢占模型选择
这是 RT 补丁最核心的配置项,决定了内核的抢占行为。在 Preemption Model 菜单下,共有四个选项:
| 配置选项 | 内核符号 | 描述 | 适用场景 |
|---|---|---|---|
| No Forced Preemption (Server) | CONFIG_PREEMPT_NONE |
无强制抢占,吞吐量优先 | 服务器、批处理系统 |
| Voluntary Kernel Preemption (Desktop) | CONFIG_PREEMPT_VOLUNTARY |
在特定自愿抢占点可抢占 | 桌面系统、多媒体 |
| Preemptible Kernel (Low-Latency Desktop) | CONFIG_PREEMPT |
内核态大部分代码可抢占 | 低延迟桌面、音频处理 |
| Fully Preemptible Kernel (Real-Time) | CONFIG_PREEMPT_RT_FULL |
完全可抢占,包括中断上下文 | 硬实时系统、工业控制 |
关键选择: 对于高精度定时器驱动开发,必须选择 Fully Preemptible Kernel (Real-Time),即
CONFIG_PREEMPT_RT_FULL。这是 RT 补丁的核心价值所在,它使包括中断处理在内的几乎所有内核代码都可被高优先级实时任务抢占。
4.2.3 PREEMPT_RT_FULL 的深层影响
选择 CONFIG_PREEMPT_RT_FULL 后,内核行为发生以下关键变化:
- 中断线程化: 所有中断处理程序(除少数标记为
IRQF_NO_THREAD的)都运行在可被抢占的内核线程上下文中,避免了中断上下文导致的不可抢占问题。 - 自旋锁可抢占: 普通自旋锁被替换为
rt_mutex基底的实现,持有锁的线程可被更高优先级的任务抢占,降低了优先级反转风险。 - RCU 抢占支持: RCU 读侧临界区可被抢占,进一步减少了不可抢占区间。
- 高精度定时器: 启用
CONFIG_HIGH_RES_TIMERS后,定时器精度可达纳秒级,且定时器回调在可抢占的软中断或线程上下文中执行。
4.2.4 其他关键 RT 配置选项
除了抢占模型,以下配置选项对实时性能和高精度定时器驱动至关重要:
| 配置项 | 推荐值 | 说明 |
|---|---|---|
CONFIG_HIGH_RES_TIMERS |
y | 启用高精度定时器,提供纳秒级定时精度,是 hrtimer 驱动的基础 |
CONFIG_PREEMPT_RT_FULL |
y | 完全可抢占内核,RT 补丁的核心选项 |
CONFIG_NO_HZ_FULL |
y | 全无滴答模式,减少周期性定时器中断对实时任务的干扰 |
CONFIG_IRQ_FORCED_THREADING |
y | 强制中断线程化,确保所有中断在可抢占上下文中处理 |
CONFIG_RCU_NOCB_CPU |
y | 将 RCU 回调卸载到专用线程,减少对实时 CPU 的干扰 |
CONFIG_CPU_FREQ |
n | 建议禁用 CPU 频率调节,避免频率切换引入不可预测的延迟 |
配置技巧: 使用
make menuconfig 时,可按 / 键搜索配置项名称(如 PREEMPT_RT_FULL),快速定位到对应菜单。配置完成后,建议将配置文件保存为 .config,并执行 make olddefconfig 自动处理依赖关系。
4.3 配置验证与编译
4.3.1 验证配置是否正确
配置完成后,可通过以下命令检查关键选项是否生效:
# 检查 PREEMPT_RT_FULL 是否启用
grep CONFIG_PREEMPT_RT_FULL .config
# 检查高精度定时器
grep CONFIG_HIGH_RES_TIMERS .config
# 检查中断线程化
grep CONFIG_IRQ_FORCED_THREADING .config
预期输出应显示 =y,例如:
CONFIG_PREEMPT_RT_FULL=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_IRQ_FORCED_THREADING=y
4.3.2 编译与安装
# 编译内核(使用 -jN 并行编译,N 为 CPU 核心数)
make -j$(nproc)
# 编译模块
make modules_install
# 安装内核
make install
# 更新引导配置(以 GRUB 为例)
update-grub
注意: 首次编译 RT 内核可能需要较长时间(30 分钟到数小时不等)。建议使用
make -j$(nproc) 充分利用多核性能。如果编译过程中出现错误,请检查依赖包是否完整,如 flex、bison、libncurses-dev 等。
4.3.3 启动验证
重启并选择新编译的内核启动后,通过以下方式验证 RT 内核是否正常运行:
# 查看内核版本
uname -a
# 输出应包含 PREEMPT_RT 字样,如:
# Linux hostname 6.1.38-rt13 #1 SMP PREEMPT_RT ...
# 检查实时调度策略是否可用
chrt -m | grep FIFO
# 应显示 SCHED_FIFO 和 SCHED_RR 的优先级范围
验证要点:
uname -a 输出中的 PREEMPT_RT 标志是 RT 内核生效的最直接证据。同时,/proc/sys/kernel/sched_rt_runtime_us 和 /proc/sys/kernel/sched_rt_period_us 文件的存在也表明 RT 调度器已启用。
4.4 常见配置问题与排查
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
编译时提示 undefined reference to `rt_mutex' |
未正确选择 CONFIG_PREEMPT_RT_FULL |
返回 menuconfig,确认 Preemption Model 选择为 Fully Preemptible Kernel |
启动后 uname -a 不显示 PREEMPT_RT |
引导加载器未加载新内核 | 检查 GRUB 默认启动项,使用 grub-set-default 设置新内核 |
| 高精度定时器无法达到纳秒精度 | CONFIG_HIGH_RES_TIMERS 未启用 |
检查 .config 文件,确保该选项为 =y |
| 实时任务调度延迟仍然较高 | CPU 频率调节或电源管理干扰 | 禁用 CONFIG_CPU_FREQ 和 CONFIG_CPU_IDLE,或使用 cpupower 设置 performance 策略 |
调试工具: 使用
cyclictest(来自 rt-tests 包)可以测量内核的实时延迟,帮助验证配置效果。命令示例:cyclictest -m -n -p 99 -h 100 -i 1000 -l 100000。最大延迟应保持在微秒级甚至更低。