第4章:输出产物分析——output/images目录详解

Buildroot编译完成后,所有成果都集中在 output/images 目录下。我第一次看到这个目录时,说实话有点懵——一堆文件,后缀各异,到底哪个才是我们需要的?

今天我就带你逐个拆解。你想想看,嵌入式系统启动需要什么?无非是:内核、根文件系统、设备树。嗯,这三个东西,就是images目录的核心产出。

4.1 目录概览:一张图看懂

先给你一张结构图,把整体脉络理清楚:

output/images 目录结构 zImage Linux内核镜像 rootfs.cpio 内存文件系统 rootfs.ext4 磁盘文件系统 *.dtb 设备树文件 启动流程 Bootloader → 加载zImage → 解析dtb → 挂载rootfs (cpio用于initramfs,ext4用于磁盘存储)

4.2 zImage:内核的“可执行文件”

zImage 就是编译好的Linux内核。说白了,它跟你在PC上看到的 vmlinuz 是一个东西,只不过针对ARM架构做了压缩。

我个人习惯用 file 命令看一眼:

$ file output/images/zImage
zImage: Linux kernel ARM boot executable zImage (little-endian)

这里有个关键点:zImage 是自解压的。Bootloader把它加载到内存后,它会自己解压,然后跳转到入口地址。我在项目中遇到过一个问题——明明内核编译成功了,但板子就是起不来。后来发现是Bootloader加载地址不对,zImage自解压时把自己覆盖了。嗯,这种坑踩过一次就记住了。

小技巧: 如果你用U-Boot,可以用 bootz 命令直接启动zImage。如果内核太大,也可以用 uImage(在zImage前面加了个U-Boot头)。

4.3 rootfs.cpio:内存里的“临时家园”

rootfs.cpio 是一个打包的根文件系统。它用cpio格式(不是tar哦),专门给initramfs用的。

为什么需要它?因为内核启动时,磁盘驱动可能还没加载。这时候内核需要先挂载一个临时的根文件系统,加载必要的驱动,然后再切到真正的磁盘根文件系统。

我记得第一次调试时,发现系统启动到一半卡住了。检查日志才发现,initramfs里少了 dev 目录的设备节点。后来我在Buildroot配置里勾选了 BR2_ROOTFS_DEVICE_CREATION_STATIC,问题就解决了。

注意: cpio文件系统是放在内存里的。如果根文件系统很大(比如超过64MB),建议用ext4而不是cpio。否则内存压力会很大。

4.4 rootfs.ext4:磁盘上的“永久家园”

rootfs.ext4 是一个ext4格式的磁盘镜像。你可以直接把它烧写到SD卡、eMMC或NAND Flash上。

dd 命令就能烧写:

$ sudo dd if=output/images/rootfs.ext4 of=/dev/sdX bs=1M status=progress

这里有个细节:ext4镜像的大小是固定的。如果你在Buildroot里设置了 BR2_TARGET_ROOTFS_EXT2_SIZE,那么生成的镜像就是那个大小。我建议设成实际需要的1.5倍左右,留点余量。

文件系统类型 适用场景 优点 缺点
cpio initramfs、内存启动 启动快、不占磁盘 占用内存、容量有限
ext4 磁盘存储、产品量产 容量大、支持日志 需要磁盘驱动
squashfs 只读文件系统 压缩率高、防篡改 不能写
核心区别: cpio是“用完即走”的临时方案,ext4是“长期居住”的正式方案。产品量产时,99%的情况用ext4。

4.5 dtb文件:硬件的“身份证”

*.dtb 是设备树二进制文件。它告诉内核:你的板子上有哪些硬件、内存多大、外设接在哪个GPIO上。

设备树源文件是 .dts,编译后变成 .dtb。Buildroot会自动编译你指定的设备树文件。

我曾经犯过一个低级错误:给A板子编译了B板子的dtb。结果内核启动时,GPIO初始化全乱套了,屏幕不亮、网口不通。排查了半天才发现是dtb搞错了。所以我现在每次烧写前都会确认一下:

$ strings output/images/board.dtb | grep model
model = "My Custom Board v2.0";

嗯,确认model名字对得上,再烧写。

4.6 其他文件:别忽略它们

除了上面四个核心文件,images目录里还有一些“配角”:

  • u-boot.bin:如果你选了U-Boot,这里就是Bootloader镜像
  • sdcard.img:完整的SD卡镜像,包含分区表和所有文件
  • rootfs.tar:根文件系统的tar包,方便手动解压到磁盘
  • *.its:FIT image的配置文件,用于打包多个镜像

我个人习惯是:开发阶段用 zImage + dtb + rootfs.cpio 通过TFTP启动,调试方便。量产阶段用 sdcard.imgrootfs.ext4 烧写到板载存储。

避坑指南: 我曾经直接拿 rootfs.ext4 烧写到NAND Flash,结果启动失败。后来发现NAND需要UBIFS格式,ext4不支持。所以一定要根据你的存储介质选择合适的文件系统格式。

4.7 总结:一张表记住核心

文件 作用 启动阶段 我的建议
zImage Linux内核 Bootloader之后 保持默认,除非需要调试
rootfs.cpio 临时根文件系统 内核启动初期 用于initramfs,别太大
rootfs.ext4 永久根文件系统 initramfs之后 产品量产首选
*.dtb 硬件描述 内核启动时 确认板子型号匹配

好了,output/images目录里的东西,你现在应该心里有数了。下次编译完Buildroot,打开这个目录,你就能一眼认出每个文件是干什么用的。这就是经验积累的过程——见得多了,自然就熟了。


公众号:蓝海资料掘金营,微信deep3321