4. Intel平台实时内核构建与启动
在工业边缘设备上,实时性不是“装完系统就自动具备”的属性,而是由内核配置、抢占模型、启动参数和硬件隔离共同决定的结果。本节以 Intel x86_64 平台(如 Core i5/i7、Xeon E3、Atom x6000 系列)为例,说明如何从源码构建一个可用的 PREEMPT_RT 内核,并完成启动与验证。
一、内核配置裁剪:先做减法,再做实时化
实时内核的第一步不是打开 PREEMPT_RT,而是裁剪。工业边缘设备通常只需要有限的驱动和子系统,冗余模块会带来中断抖动、内存占用和启动时间增加。建议以发行版配置为基线,使用 make olddefconfig 保留必要项,再逐项关闭不需要的功能。
裁剪时重点关注以下方向:关闭未使用的文件系统(如 btrfs、f2fs、nfs)、关闭无线与蓝牙子系统、关闭虚拟化与容器相关选项(若不需要)、关闭调试与追踪中非必要项(如 FTRACE、KPROBES 可保留但不宜全开)、关闭电源管理中会引入延迟的 C-state 深度策略。对于 Intel 平台,CONFIG_INTEL_IDLE、CONFIG_CPU_FREQ 与 CONFIG_X86_ACPI_CPP 需要结合实时需求评估:实时任务通常建议锁定频率、禁用深度 C-state,因此可关闭 CONFIG_INTEL_IDLE 或通过启动参数限制。
# 以发行版配置为基线
cp /boot/config-$(uname -r) .config
make olddefconfig
# 关闭典型非必要项(示例)
scripts/config --disable CONFIG_BTRFS_FS
scripts/config --disable CONFIG_BLUETOOTH
scripts/config --disable CONFIG_WIRELESS
scripts/config --disable CONFIG_KVM
scripts/config --disable CONFIG_INTEL_IDLE
scripts/config --enable CONFIG_PREEMPT_RT
make olddefconfig
裁剪后应检查 .config 中 CONFIG_PREEMPT_RT=y 是否生效,并确认 CONFIG_HZ 取值。工业实时场景常用 CONFIG_HZ_1000,兼顾调度粒度与开销;若任务周期在毫秒级,1000Hz 通常足够,过高会增加定时器中断负担。
二、PREEMPT_RT 集成:从补丁到可启动内核
PREEMPT_RT 的集成方式取决于内核版本。5.15 之前通常使用 patch-*.patch 补丁;5.15 之后 RT 补丁逐步进入主线,6.1 以后可直接使用 linux-rt 分支或 PREEMPT_RT 配置项。以 6.1 为例,推荐直接使用 RT 维护分支:
git clone --depth 1 -b v6.1-rt https://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git
cd linux-rt-devel
make x86_64_defconfig
scripts/config --enable CONFIG_PREEMPT_RT
scripts/config --enable CONFIG_HZ_1000
make olddefconfig
make -j$(nproc) bindeb-pkg
编译完成后会生成 linux-image-*.deb 与 linux-headers-*.deb。安装后需确认 /boot 下出现新内核与 initrd,并更新引导项。若使用 UEFI 启动,还需确保 CONFIG_EFI 与 CONFIG_EFI_STUB 已启用,否则可能出现“内核已安装但无法引导”的情况。
三、启动参数调优:把抖动压到最低
启动参数是实时性的第二道闸门。以下参数在 Intel 平台上较为常用,建议写入 GRUB 的 GRUB_CMDLINE_LINUX:
GRUB_CMDLINE_LINUX="
isolcpus=2,3
nohz_full=2,3
rcu_nocbs=2,3
intel_pstate=disable
processor.max_cstate=1
intel_idle.max_cstate=0
idle=poll
skew_tick=1
tsc=reliable
nmi_watchdog=0
audit=0
quiet
"
其中 isolcpus 与 nohz_full 将 CPU2、CPU3 从通用调度中隔离,rcu_nocbs 把 RCU 回调移出隔离核,idle=poll 避免进入 C-state 带来的唤醒延迟,skew_tick=1 错开各核 tick 中断,nmi_watchdog=0 关闭 NMI 看门狗以减少干扰。注意:idle=poll 会提高功耗与温度,在无风扇边缘设备上需评估散热。
四、实时性验证:用数据判断是否达标
验证工具首选 cyclictest,它通过高精度定时器测量唤醒延迟。典型命令如下:
cyclictest -m -p 80 -t 2 -a 2,3 -i 1000 -l 100000 -h 400
参数含义:-m 锁定内存,-p 80 设置实时优先级,-t 2 两个线程,-a 2,3 绑定到隔离核,-i 1000 周期 1000 微秒,-l 100000 循环次数,-h 400 输出延迟直方图。判断标准不是“平均值”,而是最大延迟(Max)。工业运动控制通常要求 Max 小于 100 微秒,一般边缘采集可放宽到 200~500 微秒。若 Max 明显偏大,应检查是否有未隔离的中断、SMI、电源管理或驱动线程干扰。
五、常见启动问题排查
实时内核启动失败通常集中在三类:引导阶段、抢占未生效、延迟不达标。引导阶段最常见的是 initrd 未更新或 EFI stub 缺失,表现为卡在 “Loading initial ramdisk” 或直接回到固件界面。此时应确认 /boot/initrd.img-$(uname -r) 存在,并检查 grub.cfg 中 linux 行指向新内核。
抢占未生效的典型现象是 uname -a 输出不带 -rt 后缀,或 /sys/kernel/realtime 不存在。这通常是因为安装后未切换默认启动项,或 CONFIG_PREEMPT_RT 在 olddefconfig 中被覆盖。建议每次编译后执行 grep PREEMPT_RT .config 确认。
延迟不达标时,先看 cyclictest 的 Max 是否集中在某个核。若隔离核上仍有中断,可用 cat /proc/interrupts 查看中断分布,并通过 echo <mask> > /proc/irq/<n>/smp_affinity 将非实时中断迁移到非隔离核。此外,BIOS 中的 SMI、超线程、Turbo Boost 也可能引入抖动,建议在实时场景下关闭超线程与 Turbo,并锁定频率。
.config、GRUB 参数和 cyclictest 结果一并归档,形成该硬件平台的“实时基线”,后续升级内核时可直接对比。完成以上步骤后,一个可用的 Intel 平台实时内核应具备:uname -a 显示 RT 标识、隔离核上 cyclictest Max 稳定在目标阈值内、系统启动无异常报错。此时再进入应用层实时任务设计,才有可靠的底层保障。