4. 基于Buildroot的汽车Linux最小系统构建
说实话,Buildroot 这东西,我第一次接触的时候觉得它挺「土」的。没有 Yocto 那种复杂的层叠结构,也没有 OpenEmbedded 的庞大生态。但干得久了你会发现,做汽车嵌入式 Linux,很多时候要的不是大而全,而是小而精。Buildroot 恰恰擅长这个。
这一章,我们就拿它来给 QEMU virt ARM64 平台搭一个最小系统。顺便把汽车上常用的 libsocketcan 和 GStreamer 塞进去。嗯,这里要注意,「最小」不代表「简陋」,而是指只包含你真正需要的东西。
4.1 为什么选 Buildroot?
我个人习惯把构建系统分成两类:
- Yocto:适合大团队、多平台、需要长期维护的产品线。功能强,但学习曲线陡,构建一次够喝杯咖啡再睡一觉。
- Buildroot:适合原型验证、单板定制、快速迭代。配置简单,编译快,特别适合我们做 QEMU 仿真——你总不想每次改个配置都等半小时吧?
我在项目中遇到过好几次这样的情况:用 Yocto 搭环境花了两周,最后发现客户要的只是 CAN 通信加个视频流。Buildroot 一下午搞定。所以,工具选对了,事半功倍。
make menuconfig 选择目标架构、内核版本、库和工具链,然后自动下载、编译、打包,最终生成内核镜像 Image 和根文件系统 rootfs.cpio。
4.2 配置 Buildroot 针对 QEMU virt ARM64
先下载 Buildroot。我建议用长期支持版本,比如 2023.02.x 或 2024.02.x,稳定一些。
wget https://buildroot.org/downloads/buildroot-2024.02.tar.gz
tar xf buildroot-2024.02.tar.gz
cd buildroot-2024.02
然后开始配置。运行:
make qemu_aarch64_virt_defconfig
这个默认配置已经帮我们选好了 ARM64 架构、QEMU virt 机器类型、内核版本和基础文件系统。但离「汽车最小系统」还差几步。
接着执行:
make menuconfig
这里我列一下必须改的几项:
| 配置项 | 路径 | 推荐值 | 说明 |
|---|---|---|---|
| Target Architecture | Target options | AArch64 (little endian) | ARM64 架构 |
| Target Binary Format | Target options | ELF | 标准格式 |
| Kernel binary format | Kernel | Image | QEMU 需要 raw 镜像 |
| Root filesystem | Filesystem images | cpio the root filesystem | initramfs 方式启动 |
| Enable MMU | Target options | Yes | 必须开启 |
4.3 集成汽车常用库
汽车嵌入式 Linux 里,有两个库几乎绕不开:libsocketcan 和 GStreamer。前者是 CAN 总线通信的瑞士军刀,后者是多媒体处理的标配。
4.3.1 添加 libsocketcan
在 make menuconfig 中搜索 libsocketcan:
/libsocketcan
然后勾选:
Target packages → Networking → libsocketcan
这个库提供了 socketcan 接口的封装,包括打开/关闭 CAN 设备、设置波特率、发送/接收帧等。我当年做 T-Box 项目时,就是靠它和 can-utils 配合,在三天内调通了 CAN 收发。
顺便把 can-utils 也加上:
Target packages → Networking → can-utils
这样你就能在目标系统里用 candump、cansend 等命令了。
4.3.2 添加 GStreamer
GStreamer 在汽车里主要用来处理摄像头视频流、音频播放、RTSP 流媒体等。配置路径:
Target packages → Audio and video applications → gstreamer1
建议勾选以下插件包:
gst1-plugins-base:基础元素,如 videotestsrc, audiotestsrcgst1-plugins-good:常用编解码器,如 jpeg, png, v4l2gst1-plugins-bad:部分实验性插件,如 rtspgst1-libav:FFmpeg 封装,支持 H.264/H.265
glib 或 libffi,手动勾上就行。
4.4 生成根文件系统与内核镜像
配置完成后,执行编译:
make -j$(nproc)
第一次编译会下载所有源码包,时间取决于网络。我建议用代理或提前下载好源码包放到 dl/ 目录下。
编译成功后,在 output/images/ 下会生成:
| 文件 | 说明 |
|---|---|
Image |
ARM64 内核镜像,QEMU 直接使用 |
rootfs.cpio |
根文件系统,initramfs 格式 |
qemu_aarch64_virt.dtb |
设备树文件,描述硬件拓扑 |
start-qemu.sh |
自动生成的 QEMU 启动脚本 |
你可以直接用 start-qemu.sh 启动,也可以手动执行:
qemu-system-aarch64 \
-M virt \
-cpu cortex-a72 \
-smp 2 \
-m 1G \
-kernel output/images/Image \
-initrd output/images/rootfs.cpio \
-append "console=ttyAMA0 root=/dev/ram0" \
-nographic
启动后,你会看到一个精简的 Linux shell。输入 candump --help 和 gst-launch-1.0 --help 验证库是否安装成功。
4.5 整体构建流程
下面这张图总结了从配置到启动的完整流程:
4.6 避坑指南
我曾经在配置 GStreamer 时踩过一个坑:默认配置下 GStreamer 的插件包只编译核心库,不包含实际元素。结果启动后 gst-launch-1.0 videotestsrc 报错说找不到元素。后来发现需要在 menuconfig 里手动勾选 gst1-plugins-base 下的 videotestsrc 子选项。
另外,libsocketcan 依赖内核的 CAN 子系统。如果你启动 QEMU 后执行 ip link set can0 up 报错,说明内核没开启 CAN 支持。需要在 make linux-menuconfig 里勾选:
Networking support → CAN bus subsystem support
以及对应的驱动(比如 Virtual CAN driver)。
make clean 再 make,避免旧文件干扰。虽然慢一点,但能省去排查诡异问题的时间。