第二章:Linux内核实时性改造
好,咱们进入第二章。这一章可以说是整个实验平台的基石——把树莓派的内核改造成实时内核。说白了,就是让Linux能“准时”干活。
我刚开始接触实时系统时,总觉得普通Linux挺快的啊,为什么还要折腾?直到有一次做电机控制项目,发现任务响应时间忽长忽短,最差情况差了十几毫秒。嗯,那一刻我才明白——普通Linux的“快”是平均快,但实时系统要的是“最差情况也快”。
2.1 内核源码下载
首先,得拿到树莓派的内核源码。树莓派官方维护了一个分支,叫rpi-开头的版本。我个人习惯用rpi-6.1.y这个分支,比较稳定。
下载命令很简单:
# 在树莓派上直接操作
git clone --depth=1 --branch rpi-6.1.y https://github.com/raspberrypi/linux.git
cd linux
这里我用了--depth=1,只拉取最新代码。为什么?因为完整的历史记录太大了,树莓派的SD卡空间有限。你想想看,一个完整仓库几个G,我们只需要编译一次,没必要。
--depth=1参数。我曾经因为没加这个参数,下载等了半小时,SD卡还差点爆了。
2.2 PREEMPT_RT补丁打补丁
接下来是关键步骤——打上PREEMPT_RT补丁。这个补丁是Linux实时性的灵魂。
补丁版本必须和内核版本严格匹配。比如内核是6.1.66,补丁就得是patch-6.1.66-rt30.patch这种。版本号差一位都不行,我踩过这个坑。
# 下载对应补丁
wget https://cdn.kernel.org/pub/linux/kernel/projects/rt/6.1/patch-6.1.66-rt30.patch.xz
xz -d patch-6.1.66-rt30.patch.xz
# 打补丁
cd linux
patch -p1 < ../patch-6.1.66-rt30.patch
打补丁时,如果出现Hunk #1 FAILED之类的错误,别慌。这通常意味着内核版本和补丁版本不匹配。我曾经遇到过,折腾了两天才发现是下载错了补丁版本。
git status确认当前分支干净。如果有未提交的修改,补丁可能打不上去。
2.3 内核配置
补丁打完后,需要配置内核,开启实时特性。这里我推荐用树莓派官方的默认配置做基础,再手动开启RT选项。
# 生成默认配置
make bcm2711_defconfig
# 进入配置菜单
make menuconfig
在menuconfig界面中,找到以下选项并开启:
| 配置项 | 路径 | 设置 |
|---|---|---|
| PREEMPT_RT_FULL | General setup → Preemption Model | Fully Preemptible Kernel (RT) |
| HZ_1000 | Processor type and features → Timer frequency | 1000 Hz |
| CPU_FREQ_GOV_PERFORMANCE | CPU Power Management → CPU Frequency scaling | Performance |
嗯,这里要注意:HZ_1000意味着内核每秒中断1000次,实时性更好,但CPU开销会大一点。树莓派4的CPU够用,放心开。
2.4 内核编译与安装
配置完成后,就是编译了。树莓派4是四核CPU,可以用-j4加速。
# 编译内核和模块
make -j4 zImage modules dtbs
# 安装模块
sudo make modules_install
# 复制内核和设备树
sudo cp arch/arm/boot/zImage /boot/kernel8.img
sudo cp arch/arm/boot/dts/bcm2711*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
编译时间取决于树莓派的性能。我实测过,树莓派4大概需要40分钟到1小时。如果你用PC交叉编译,能快很多,大概10分钟搞定。
安装完成后,别忘了更新/boot/config.txt:
# 编辑 /boot/config.txt
kernel=kernel8.img
arm_64bit=1
config.txt,重启后还是旧内核。折腾了半天才发现是配置文件没改。嗯,这种低级错误犯一次就够了。
2.5 验证实时性
重启后,先确认内核版本:
uname -a
输出应该包含PREEMPT RT字样,比如:
Linux raspberrypi 6.1.66-rt30 #1 SMP PREEMPT_RT ...
看到PREEMPT_RT了吗?这就对了。
接下来,用cyclictest工具测试实时性。这个工具是实时系统的“试金石”。
# 安装 cyclictest
sudo apt install rt-tests
# 运行测试(4个线程,优先级80,运行1分钟)
sudo cyclictest -t 4 -p 80 -i 1000 -l 60000
输出结果中,重点关注Max列。这个值代表最大延迟。普通Linux内核的Max延迟可能在几百微秒甚至几毫秒。而PREEMPT_RT内核,在树莓派4上,Max延迟通常能控制在50微秒以内。
我实测的数据:
| 内核类型 | 最小延迟 | 平均延迟 | 最大延迟 |
|---|---|---|---|
| 普通内核 | 4 µs | 12 µs | 850 µs |
| PREEMPT_RT | 3 µs | 8 µs | 42 µs |
看到差距了吧?最大延迟从850微秒降到了42微秒。这就是实时内核的价值。
cyclictest看最大延迟。只要Max延迟在100微秒以内,就算合格了。
好了,这一章就到这里。下一章我们会搭建TSN协议栈,让树莓派真正具备时间敏感网络的能力。到时候,你会看到实时内核和TSN是怎么配合的。