4. 开发环境搭建
构建一个可运行的 PREEMPT_RT 内核是进行实时性测试的基础。本章将系统性地讲解从零搭建嵌入式 Linux 实时开发环境的完整流程,涵盖交叉编译工具链的安装、内核源码的获取与配置、基于 menuconfig 的实时特性启用,以及内核的编译与目标板部署。正确的环境搭建是后续所有性能验证工作的前提。
环境概览: 本教程以 x86_64 主机 作为开发机,目标平台为 ARM Cortex-A 系列(如 BeagleBone Black 或 Raspberry Pi 3/4)。所有步骤均经过验证,但请根据实际目标板调整架构参数。
4.1 交叉编译工具链安装
嵌入式系统资源受限,无法在目标板上直接编译内核。因此,需要在性能强大的主机上使用交叉编译工具链,生成目标架构的可执行代码。
4.1.1 工具链选择与下载
推荐使用 Linaro 提供的 GNU 工具链,它针对 ARM 架构进行了优化且社区活跃。根据目标架构选择对应的版本:
| 目标架构 | 工具链前缀 | 推荐版本 | 下载来源 |
|---|---|---|---|
| ARM 32-bit (armv7l) | arm-linux-gnueabihf- |
gcc-linaro-7.5.0 | Linaro Release |
| ARM 64-bit (aarch64) | aarch64-linux-gnu- |
gcc-linaro-7.5.0 | Linaro Release |
4.1.2 安装与配置环境变量
以下以 ARM 32-bit 工具链为例,展示安装步骤:
# 1. 下载并解压工具链
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
tar -xf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/
# 2. 设置环境变量(建议写入 ~/.bashrc)
export CROSS_COMPILE=/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
export ARCH=arm
# 3. 验证安装
${CROSS_COMPILE}gcc --version
# 输出应显示 gcc (Linaro GCC 7.5-2019.12) 版本信息
关键检查点: 务必确认
CROSS_COMPILE 变量以连字符结尾(如 arm-linux-gnueabihf-),否则内核构建系统将无法正确调用工具链。
4.2 内核源码获取与实时补丁集成
PREEMPT_RT 内核由标准 Linux 内核加上实时补丁集构成。获取源码有两种主流方式:
- 方式一(推荐): 从 kernel.org 下载主线内核源码,再单独下载对应版本的 RT 补丁。
- 方式二: 直接克隆维护在
git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git的实时内核开发分支。
4.2.1 下载主线内核与 RT 补丁
# 下载内核源码(以 v5.10 为例)
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.100.tar.xz
tar -xf linux-5.10.100.tar.xz
cd linux-5.10.100
# 下载对应的 RT 补丁
wget https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.10/patch-5.10.100-rt57.patch.xz
xz -d patch-5.10.100-rt57.patch.xz
# 应用补丁
patch -p1 < patch-5.10.100-rt57.patch
4.2.2 验证补丁应用状态
补丁应用成功后,内核源码根目录会生成 localversion-rt 文件,且 Makefile 中的 EXTRAVERSION 字段会包含 -rt57。可通过以下命令确认:
head -5 Makefile | grep EXTRAVERSION
# 输出示例:EXTRAVERSION = -rt57
4.3 构建系统配置(menuconfig)
内核配置是决定实时性能的关键步骤。使用 make menuconfig 进入图形化配置界面,必须确保 PREEMPT_RT 相关选项被正确启用。
4.3.1 加载默认配置并启动 menuconfig
# 加载目标板默认配置(以 BeagleBone Black 为例)
make omap2plus_defconfig
# 启动图形化配置界面
make menuconfig
4.3.2 关键配置项检查清单
在 menuconfig 界面中,按以下路径确认配置:
| 配置路径 | 选项名称 | 必须状态 | 说明 |
|---|---|---|---|
| General setup —> Preemption Model | Fully Preemptible Kernel (Real-Time) |
选中 | 启用完整实时抢占,这是 RT 内核的核心 |
| Processor type and features —> Timer frequency | 1000 Hz |
选中 | 高时钟频率降低调度延迟 |
Kernel Features —> High Resolution Timer Support |
[*] |
启用 | 提供纳秒级定时精度 |
Real-time sub-system —> Futex / PI Futex |
[*] |
启用 | 支持优先级继承互斥锁 |
配置验证命令: 退出 menuconfig 后,可使用
grep -E "PREEMPT_RT|HZ_1000|HIGH_RES_TIMERS" .config 快速确认关键选项已生效。
4.4 编译与部署 PREEMPT_RT 内核
配置完成后,进入编译阶段。嵌入式内核编译通常分为内核镜像(zImage/Image)和设备树(DTB)两部分。
4.4.1 编译内核与模块
# 编译内核镜像(使用 -jN 并行编译,N 为 CPU 核心数)
make -j4 zImage
# 编译设备树
make -j4 dtbs
# 编译内核模块
make -j4 modules
4.4.2 安装模块到目标文件系统
# 指定目标板根文件系统路径(示例:/srv/nfs/rootfs)
make modules_install INSTALL_MOD_PATH=/srv/nfs/rootfs
4.4.3 部署到目标板
根据目标板的启动方式(SD 卡、NFS、TFTP),部署步骤略有不同。以下为 SD 卡部署的通用流程:
- 挂载 SD 卡分区: 将 SD 卡插入主机,挂载启动分区(通常为 FAT32)和根文件系统分区。
- 复制内核镜像:
cp arch/arm/boot/zImage /media/boot/ - 复制设备树:
cp arch/arm/boot/dts/am335x-boneblack.dtb /media/boot/ - 更新引导配置: 修改
uEnv.txt或extlinux.conf,确保引导加载程序指向新内核。 - 安全卸载:
sync; umount /media/boot /media/rootfs
快速验证: 目标板启动后,执行
uname -a,输出应包含 PREEMPT RT 字样,例如:Linux beaglebone 5.10.100-rt57 #1 SMP PREEMPT_RT ...
4.5 常见问题与排错
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
编译报错:undefined reference to... |
工具链版本与内核版本不兼容 | 升级或降级工具链至 Linaro 7.5 或更新版本 |
启动时内核 panic:Kernel panic - not syncing: VFS |
根文件系统路径或类型配置错误 | 检查 root= 参数和 CONFIG_EXT4_FS 等文件系统支持 |
实时特性未生效:uname -a 显示 PREEMPT 而非 PREEMPT_RT |
menuconfig 中未正确选择 Fully Preemptible Kernel |
重新执行 make menuconfig 并确认抢占模型选项 |
性能基线提醒: 首次成功启动 PREEMPT_RT 内核后,建议立即使用
cyclictest 工具记录一组基线延迟数据(参考第 5 章)。这有助于后续优化时对比效果。