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

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_TIMERS、CONFIG_IRQ_FORCED_THREADING)会被强制设为 y,哪怕你手动关掉也会被覆盖。
- 检查方法:编译前确认
.config中有CONFIG_PREEMPT_RT_FULL=y,没有就说明没真正启用 -
CONFIG_NO_HZ_IDLE和CONFIG_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 相关模块(尤其是 rtmutex、futex、irqbypass),系统会在 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,整套实时性就塌半边。










