4、Linux系统移植:Yocto构建TBOX专用系统、内核裁剪与驱动集成、文件系统定制
好,咱们进入正题。这一章讲的是Linux系统移植,说白了就是怎么给TBOX这个硬件“装上灵魂”。Yocto、内核裁剪、只读文件系统——这些词听着挺唬人,但拆开来看,每一步都有它的道理。我当年第一次用Yocto的时候,光编译就等了六个小时,结果还报错……嗯,后来才发现是源没配好。咱们今天争取不让你走这个弯路。
4.1 Yocto构建TBOX专用系统
Yocto是什么?它是一个构建嵌入式Linux系统的工具集。你想想看,TBOX这种车规级设备,不可能像PC一样装个Ubuntu就完事。我们需要一个“刚刚好”的系统——不多一个包,不少一个驱动。
我个人习惯用Yocto的 Poky 作为基础参考系统。为什么?因为它稳定,社区活跃,而且对ARM架构支持得特别好。TBOX的SoC大多是ARM Cortex-A系列,比如NXP的i.MX8、瑞萨的R-Car,Poky都能很好地适配。
构建流程大致是这样的:
- 初始化环境:下载Poky,运行
oe-init-build-env脚本。 - 配置目标机器:在
local.conf中设置MACHINE变量,比如MACHINE = "imx8qm-var-som"。 - 添加Meta层:TBOX需要额外的驱动和库,比如CAN通信、GNSS解析、V2X协议栈。这些都要通过
bblayers.conf引入。 - 定制镜像:用
bitbake core-image-minimal打底,再往里面加你需要的包。
关键点:TBOX的系统镜像一定要“瘦”。我见过有人把Python、GCC都编译进去,结果镜像200多MB,启动慢不说,还容易出安全漏洞。记住,TBOX不是开发板,是量产产品。
这里有个小技巧:用 IMAGE_INSTALL_append 来添加包,而不是直接改 local.conf。这样方便维护,也方便不同项目复用。
# 在你的自定义meta层中,比如 meta-tbox/recipes-core/images/tbox-image.bb
IMAGE_INSTALL_append = " \
can-utils \
libsocketcan \
gpsd \
openssl \
v2x-stack \
"
我曾经在一个项目里,因为漏加了 can-utils,导致调试CAN总线时手忙脚乱。后来我学乖了,每次构建前都列一个“必装清单”,贴在工位上。
4.2 内核裁剪与驱动集成
内核裁剪,说白了就是“去掉你不需要的,留下你必需的”。TBOX的内核不需要支持显卡、声卡、USB键盘这些外设。但CAN、SPI、I2C、以太网这些一个都不能少。
我一般这样操作:
- 获取内核源码:从SoC厂商那里拿到BSP包,里面通常有打好了补丁的内核。
- 配置内核:运行
make menuconfig,逐项检查。 - 裁剪模块:把不需要的驱动都去掉,比如
CONFIG_SOUND、CONFIG_USB_HID这些。 - 集成驱动:把TBOX特有的驱动加进去,比如V2X模组的PCIE驱动、GNSS的串口驱动。
提示:我个人习惯把内核配置保存为 defconfig,放在Yocto的recipes-kernel目录下。这样每次构建都能复现,不会出现“上次还能跑,这次怎么不行了”的尴尬。
驱动集成这块,最容易出问题的是 设备树。TBOX的硬件连接千奇百怪——CAN控制器挂在哪条SPI总线上?GNSS模块用哪个UART?这些都要在设备树里写清楚。
// 设备树片段:tbox.dts
&uart3 {
status = "okay";
pinctrl-0 = &pinctrl_uart3;
gnss: gnss@0 {
compatible = "u-blox,neo-m9n";
current-speed = <115200>;
};
};
&ecspi2 {
status = "okay";
can0: can@0 {
compatible = "microchip,mcp2518fd";
reg = <0>;
spi-max-frequency = <20000000>;
};
};
嗯,这里要注意:设备树的 compatible 字符串一定要和驱动里匹配的字符串完全一致。我吃过这个亏——少写了一个逗号,内核就是认不出设备。查了两天才发现,原来是手误。
4.3 文件系统定制:只读根文件系统
为什么TBOX要用只读根文件系统?你想想看,车在路上跑,系统突然写坏了一个配置文件,或者断电导致文件系统损坏——这可不是闹着玩的。只读根文件系统,就是为了保证系统在任何情况下都能正常启动。
实现方式其实不复杂:
- 构建根文件系统:用Yocto的
core-image-minimal为基础,添加你需要的库和应用。 - 制作只读镜像:使用
squashfs或ext4只读挂载。 - 分离可写分区:把日志、配置数据放到一个单独的可写分区,比如
/data或/var。
我推荐用 squashfs,因为它压缩率高,而且天生只读。一个原本100MB的根文件系统,压缩后可能只有40MB。对于TBOX这种存储空间有限的设备来说,非常实用。
警告:千万不要把 /etc 也做成只读!有些应用会在运行时修改配置文件,比如V2X协议栈的证书更新。正确的做法是:/etc 用overlayfs挂载,上层是可写分区,下层是只读的squashfs。
在Yocto中,可以通过 IMAGE_FEATURES 来启用只读根文件系统:
# local.conf 或你的镜像配方中
IMAGE_FEATURES_append = " read-only-rootfs"
这样Yocto会自动帮你处理好只读挂载和可写分区的映射。但说实话,自动处理有时候并不完美。我曾经遇到一个问题:系统启动后,/var/log 写不进去,因为Yocto默认把 /var 也放在了只读分区里。后来我手动在 fstab 里加了一行,把 /var/log 挂载到可写分区才解决。
# /etc/fstab 片段
/dev/mmcblk0p2 /data ext4 defaults 0 0
/data/var/log /var/log none bind 0 0
说白了,只读根文件系统就是“用空间换安全”。你牺牲了一点灵活性,但换来了极高的可靠性。对于TBOX这种安全至上的设备,这笔买卖绝对划算。
小结
这一章的内容,说白了就是三件事:用Yocto搭骨架,用内核裁剪做减脂,用只读文件系统上保险。每一步都有坑,但只要你按照流程来,多测试、多验证,就不会出大问题。
我记得第一次给TBOX做系统移植时,光内核就编译了十几遍。每次改一个配置,就要等半小时。后来我学会了用 ccache 加速编译,还把常用的配置项记在本子上。现在再做类似项目,基本一次过。
下一章我们会讲V2X协议栈的集成,那才是真正考验功力的时候。做好准备。