Linux kernel 的 PREEMPT_RT 补丁在实时应用中的编译与测试 checklist

3次阅读

preempt_rt补丁与内核版本必须严格匹配,需按官方对应patch文件打补丁、启用config_preempt_rt_full、禁用no_hz选项、配置sched_latency_ns、验证initramfs模块完整性。

Linux kernel 的 PREEMPT_RT 补丁在实时应用中的编译与测试 checklist

PREEMPT_RT 补丁版本和内核版本必须严格匹配

打不上补丁、make menuconfig 报错或编译中途失败,八成是版本不配。PREEMPT_RT 不是通用补丁,每个 linux-5.x.y 内核都有唯一对应的 patch-5.x.y-rtz(z 是 RT 补丁序号),连小版本号差一位都可能挂。

  • 查官方发布页:https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/,按内核版本找对应 patch 文件,别用“最新版”偷懒
  • 解压顺序必须是:先解内核源码 → 进入目录 → 用 patch -p1 打补丁 → 再 <code>make clean(旧配置残留常导致奇怪的 Kconfig 错误)
  • 打完补丁后运行 scripts/checkpatch.pl --no-tree --file .config 能快速暴露是否漏打或打歪了

CONFIG_PREEMPT_RT_FULL 必须显式开启,且依赖项会自动翻转

只在 make menuconfig 里搜到 PREEMPT_RT 并勾上不够——它只是个入口开关。真正起效的是底层的 CONFIG_PREEMPT_RT_FULL,而它一开,几十个子项(比如 CONFIG_HIGH_RES_TIMERSCONFIG_IRQ_forCED_THREADING)会被强制设为 y,哪怕你手动关掉也会被覆盖。

  • 检查方法:编译前确认 .config 中有 CONFIG_PREEMPT_RT_FULL=y,没有就说明没真正启用
  • CONFIG_NO_HZ_IDLECONFIG_NO_HZ_FULL 在 RT 下默认禁用,强行打开会导致 tick 崩溃;RT 已用自己的一套无滴答调度逻辑
  • 某些驱动(如 e1000e)在 CONFIG_PREEMPT_RT_FULL=y 下需额外加 CONFIG_E1000E_DISABLE_PACKET_SPLIT=y,否则收包延迟毛刺明显

实时测试不能只跑 cyclictest,得看 sched_latency_ns 和 migration

cyclictest -t5 -p99 -i1000 -l10000 跑出来 latency sched_latency_ns 设置不当引发的周期性调度挤压。

  • 先查当前值:cat /proc/sys/kernel/sched_latency_ns,默认 6ms,对 1kHz 实时任务来说太高;建议设为 echo 1000000 > /proc/sys/kernel/sched_latency_ns(1ms)
  • chrt -f 99 taskset -c 1 ./my_rt_app 绑核 + FIFO 调度,再观察 /proc/<pid>/status</pid> 中的 voluntary_ctxt_switches —— 若远高于 nonvoluntary_ctxt_switches,说明应用主动让出太多,不是 RT 问题;若后者突增,大概率是被 migration_thread 或 ksoftirqd 抢占了
  • trace-cmd record -e sched:sched_migrate_task -e irq:irq_handler_entry 可抓到具体哪个 IRQ 触发了迁移,比盲调参数靠谱得多

initramfs 里缺 rt-kernel 模块会导致启动卡在 “Waiting for root device”

内核能编译过去、vmlinuz 能加载,但 initramfs 没打包进 RT 相关模块(尤其是 rtmutexfutexirqbypass),系统会在 early boot 阶段静默失败,表现为卡在 “Starting kernel …” 后几秒不动,串口也无输出。

  • 确认 CONFIG_INITRAMFS_SOURCE 指向的目录里包含 lib/modules/$(uname -r)/kernel/kernel/rtmutex.ko 等关键模块
  • lsinitrd /boot/initramfs-$(uname -r).img | grep -E "(rtmutex|futex|irqbypass)" 验证是否真打进去了
  • 如果用 dracut,必须加 --force-drivers "rtmutex futex irqbypass",默认 dracut 会过滤掉这些“非标准”模块

RT 内核最麻烦的从来不是编译,而是把所有依赖链上的隐含模块、启动时序、调度边界条件都对齐。漏掉一个 irqbypass.ko,或者 sched_latency_ns 多设了 2ms,整套实时性就塌半边。

text=ZqhQzanResources