实时内核PREEMPT_RT移植与性能调优实战 - 第4节

4.1 获取 Linux 内核源码

PREEMPT_RT 实时内核的构建起点是标准 Linux 内核源码。内核源码的获取方式直接影响后续补丁应用的兼容性与开发效率。本节介绍两种主流获取途径:主线内核源码与长期支持(LTS)内核源码。

4.1.1 主线内核与 LTS 内核的选择

特性 主线内核(Mainline) LTS 内核
发布周期 约 2-3 个月 2-6 年维护期
PREEMPT_RT 支持 最新补丁,但稳定性较低 官方推荐,补丁成熟度高
适用场景 原型验证、功能探索 产品级实时系统
内核版本示例 6.12-rc1 6.1.y、5.15.y、5.10.y
实战建议: 本课程所有实验均基于 LTS 内核 6.1.y 系列。LTS 内核与 PREEMPT_RT 补丁的版本匹配关系可在内核官网的补丁目录中直接查询,避免版本错配导致的编译失败。

4.1.2 使用 Git 获取内核源码

Git 方式是最推荐的源码获取方法,便于版本切换与补丁管理。以下命令克隆 Linus Torvalds 的主线仓库:

git clone --depth 1 --branch v6.1 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux

若需要完整的 Git 历史(用于补丁回溯或分支管理),去掉 --depth 1 参数即可:

git clone --branch v6.1 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
关键点: --depth 1 参数创建浅克隆(shallow clone),仅下载目标版本的文件快照,大幅减少网络传输量与磁盘占用。对于仅需编译一次的内核,浅克隆是首选。

4.1.3 直接下载源码压缩包

对于无法使用 Git 的环境,可直接从内核官网下载 tar.xz 格式的源码包:

wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.tar.xz
tar -xf linux-6.1.tar.xz
cd linux-6.1

下载后建议校验 SHA256 哈希值,确保源码完整性:

sha256sum linux-6.1.tar.xz
# 与 kernel.org 公布的哈希值比对
安全提示: 始终从 kernel.org 或其官方镜像站下载源码。第三方站点可能提供被篡改的源码包,引入安全后门或恶意代码。

4.2 PREEMPT_RT 补丁下载与打补丁

PREEMPT_RT 补丁将标准内核转换为完全可抢占的实时内核。补丁的版本必须与内核源码版本严格匹配,否则补丁应用将失败或产生不可预测的行为。

4.2.1 补丁版本匹配规则

补丁命名规则为 patch-{内核版本}-rt{补丁序号}.patch.xz。例如,针对内核 6.1 的 PREEMPT_RT 补丁文件名为 patch-6.1-rt14.patch.xz。版本匹配的精确度要求如下:

  • 主版本号必须完全一致: 6.1 内核只能使用 6.1 系列的补丁。
  • 次版本号(补丁序号)可升级: 例如 6.1-rt14 可升级到 6.1-rt15,但不可跨主版本。
  • LTS 内核的补丁: 通常以 patches-6.1.xx-rtxx.tar.gz 形式提供,包含累积补丁集。

4.2.2 下载 PREEMPT_RT 补丁

PREEMPT_RT 补丁的官方下载地址为:

wget https://cdn.kernel.org/pub/linux/kernel/projects/rt/6.1/patch-6.1-rt14.patch.xz
xz -d patch-6.1-rt14.patch.xz

解压后得到 patch-6.1-rt14.patch 文件,即可用于打补丁操作。

4.2.3 使用 patch 命令打补丁

进入内核源码根目录,执行以下命令应用补丁:

cd linux-6.1
xzcat ../patch-6.1-rt14.patch.xz | patch -p1 --dry-run
# 若无错误输出,则移除 --dry-run 正式应用
xzcat ../patch-6.1-rt14.patch.xz | patch -p1

--dry-run 参数用于模拟打补丁过程,检测是否存在冲突。若输出中无 FAILED 或 hunk 错误,则可安全移除该参数正式应用。

最佳实践: 打补丁前始终执行 --dry-run。若出现冲突,检查内核版本与补丁版本是否匹配,或使用 git am 方式(适用于 Git 仓库)获得更详细的冲突报告。

4.2.4 使用 Git am 打补丁(推荐)

若内核源码通过 Git 克隆,推荐使用 git am 命令应用补丁,它提供更好的冲突跟踪与回退能力:

git checkout v6.1
git am ../patch-6.1-rt14.patch

若补丁应用成功,Git 会创建一个新的提交记录,便于后续使用 git revert 回退补丁。若出现冲突,Git 会提示冲突文件位置,使用 git am --abort 可完全撤销本次补丁操作。

4.3 内核配置菜单详解

补丁应用完成后,下一步是配置内核。内核配置菜单(make menuconfig)提供交互式界面,用于启用或禁用内核功能。对于实时系统,有三个配置项至关重要:抢占模型(Preemption Model)、定时器频率(Timer Frequency)和 CPU 隔离(CPU Isolation)。

4.3.1 抢占模型(Preemption Model)

抢占模型决定内核响应外部事件的速度与可预测性。PREEMPT_RT 补丁添加了第四种抢占模型——Fully Preemptible Kernel (Real-Time)。四种模型的对比见下表:

抢占模型 内核配置选项 抢占延迟 适用场景
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 极低(微秒级,可预测) 工业控制、机器人、航空航天

在 menuconfig 中,进入 General Setup → Preemption Model,选择 Fully Preemptible Kernel (Real-Time)。只有正确应用了 PREEMPT_RT 补丁后,该选项才会出现。

验证方法: 配置完成后,检查 .config 文件中是否包含 CONFIG_PREEMPT_RT=y。若该选项未出现,说明补丁未正确应用或内核版本不匹配。

4.3.2 定时器频率(Timer Frequency)

定时器频率(HZ)决定内核时钟中断的触发频率。频率越高,内核调度器的响应粒度越细,但 CPU 开销也越大。实时系统需要在延迟与开销之间取得平衡。

频率值 HZ 配置选项 时钟周期 实时推荐度
100 Hz CONFIG_HZ_100 10 ms 不推荐
250 Hz CONFIG_HZ_250 4 ms 一般
300 Hz CONFIG_HZ_300 3.33 ms 可选
1000 Hz CONFIG_HZ_1000 1 ms 强烈推荐

在 menuconfig 中,进入 Processor type and features → Timer frequency,选择 1000 Hz。同时确保 CONFIG_HIGH_RES_TIMERS=y(高精度定时器)已启用,该选项通常默认开启。

性能权衡: 1000 Hz 频率下,内核每秒产生 1000 次时钟中断。对于嵌入式低功耗设备,若 CPU 资源紧张,可考虑 250 Hz 或 300 Hz,但实时延迟上限会相应增加。

4.3.3 CPU 隔离(CPU Isolation)

CPU 隔离将指定 CPU 核心从内核的通用调度器中移除,专用于运行实时任务。隔离后的核心不再处理普通进程、中断或内核线程,从而消除干扰源。

在 menuconfig 中,CPU 隔离相关配置位于:

General setup → CPU isolation
    [*] CPU isolation
    (1)   Number of CPUs to isolate (0-N)
    (0)   Isolated CPU list (bitmap, e.g. "2-3")

配置项说明:

  • Number of CPUs to isolate: 指定要隔离的 CPU 数量。例如,4 核系统中隔离 2 个核心。
  • Isolated CPU list: 使用位图格式指定具体核心编号。例如 2-3 表示隔离 CPU2 和 CPU3。

隔离后的核心还需要通过内核启动参数 isolcpus 在引导时生效:

isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3

这三个参数共同作用:

  • isolcpus:将核心从调度器中移除。
  • nohz_full:在隔离核心上关闭周期性时钟滴答。
  • rcu_nocbs:将 RCU 回调处理迁移到非隔离核心。
隔离效果验证: 系统启动后,使用 taskset -pc 0 $$ 查看当前进程的 CPU 亲和性。隔离核心上不应运行任何非实时进程。使用 cat /proc/interrupts 观察隔离核心的中断计数,应远低于非隔离核心。

4.4 内核配置流程总览

以下 SVG 图展示了从源码获取到配置完成的完整流程,以及三个关键配置项在整体流程中的位置:

内核源码获取与配置流程 获取内核源码 下载 PREEMPT_RT 补丁 应用补丁 配置抢占模型 CONFIG_PREEMPT_RT 配置定时器频率 CONFIG_HZ_1000 配置 CPU 隔离 isolcpus / nohz_full 保存 .config 文件 编译内核 关键配置项 抢占模型 + 定时器频率 + CPU 隔离 = 实时基础

4.5 配置验证与常见问题

4.5.1 验证配置是否正确

配置完成后,使用以下命令检查关键配置项是否生效:

# 检查抢占模型
grep CONFIG_PREEMPT_RT .config
# 输出应为:CONFIG_PREEMPT_RT=y

# 检查定时器频率
grep CONFIG_HZ_1000 .config
# 输出应为:CONFIG_HZ_1000=y

# 检查 CPU 隔离
grep CONFIG_CPU_ISOLATION .config
# 输出应为:CONFIG_CPU_ISOLATION=y

4.5.2 常见问题与解决方案

问题现象 可能原因 解决方案
CONFIG_PREEMPT_RT 未出现 补丁未正确应用或版本不匹配 重新检查补丁版本,使用 patch --dry-run 验证
编译时出现大量未定义符号 内核配置与补丁冲突 执行 make mrproper 清理后重新配置
隔离核心上仍有中断 未配置 nohz_full 或 rcu_nocbs 在启动参数中补充这两个选项
系统启动后实时任务延迟高 定时器频率未设置为 1000 Hz 检查 CONFIG_HZ 值,重新配置
调试技巧: 使用 make savedefconfig 生成最小化配置文件,便于排查配置项冲突。该命令会输出当前配置中所有非默认值的选项,大幅缩小问题定位范围。