1. 课程导入

在嵌入式 Linux 产品开发中,内核只负责管理硬件与提供系统调用,真正让用户“看得见、用得上”的,是根文件系统。设备上电后,内核完成初始化,会尝试挂载根文件系统,并执行其中的第一个用户态程序(通常是 /sbin/init)。如果根文件系统缺失、损坏或配置错误,系统就会停在 Kernel panic - not syncing: VFS: Unable to mount root fs 这类错误上。因此,构建一个可启动、可裁剪、可维护的根文件系统,是嵌入式 Linux 工程师的核心技能之一。

本课程围绕 Buildroot 展开。Buildroot 是一套基于 Makefile 与 Kconfig 的自动化构建框架,它把交叉编译工具链、引导程序、Linux 内核、根文件系统以及大量第三方软件包的下载、配置、编译、打包过程统一管理起来,最终输出可直接烧录的镜像。相比手工使用 BusyBox 加脚本拼装根文件系统,Buildroot 的优势在于可复现、可配置、可版本管理,并且能通过 make menuconfig 以图形化方式完成裁剪。

学习目标

  • 理解根文件系统在嵌入式 Linux 启动链路中的位置与作用,掌握 FHS 目录规范的基本约定。
  • 掌握 Buildroot 的目录结构、配置体系与构建流程,能够独立完成一次 make 全量构建。
  • 能够使用 make menuconfig 配置目标架构、工具链、系统配置与软件包集合。
  • 掌握 output/ 目录下各产物的含义,能定位 rootfs.tar、rootfs.ext4、Image 等镜像。
  • 能够通过 overlay、post-build、post-image 脚本定制根文件系统内容。
  • 具备常见启动故障的排查能力,例如串口无输出、init 找不到、库缺失、权限错误等。

核心概念

要理解 Buildroot 构建根文件系统的过程,需要先建立几个关键概念。第一是目标三元组(target triplet),例如 arm-linux-gnueabihf,它决定了交叉工具链的前缀与 ABI。第二是工具链(toolchain),Buildroot 既可以使用外部预编译工具链,也可以自行构建,后者通过 BR2_TOOLCHAIN_BUILDROOT 系列选项控制。第三是软件包(package),每个包由 Config.in 与 *.mk 描述,决定下载地址、版本、依赖与安装规则。第四是根文件系统格式,常见有 ext2/ext4、squashfs、ubifs、cpio、tar 等,选择取决于存储介质与是否只读。

根文件系统不是“一堆文件的集合”这么简单,它同时承担了设备节点、启动脚本、动态库、配置文件、用户权限与应用入口等多重职责。Buildroot 的价值,就是把这些职责用声明式配置固化下来。

整体框架

下图展示了从配置到镜像的 Buildroot 根文件系统构建主线。左侧是输入:defconfig、menuconfig 与 overlay;中间是构建引擎:下载、解压、配置、编译、安装;右侧是输出:target/ 目录树与各类根文件系统镜像。理解这条数据流,后续每一章的配置项与命令都能找到对应位置。

Buildroot 根文件系统构建主线 输入 / 配置 defconfig menuconfig overlay / 脚本 .config 构建引擎(Makefile + Kconfig) 下载 / 解压 配置 / 打补丁 交叉编译 安装到 target BusyBox / 库 / 软件包 / 设备节点 生成 rootfs 镜像 输出 / 产物 output/target/ rootfs.tar rootfs.ext4 Image / dtb 配置驱动构建,构建产出镜像,镜像烧录后由内核挂载为根文件系统

方法流程与典型场景

一次完整的 Buildroot 构建通常遵循如下流程:选择或生成配置、执行构建、检查产物、烧录验证。以常见的 ARM 开发板为例,命令序列如下:

# 1. 获取 Buildroot 源码
git clone https://gitlab.com/buildroot.org/buildroot.git
cd buildroot

# 2. 选择接近目标板的 defconfig
make qemu_aarch64_virt_defconfig

# 3. 进入图形化配置,裁剪软件包与根文件系统格式
make menuconfig

# 4. 开始构建(可使用 -j 加速)
make -j$(nproc)

# 5. 查看输出产物
ls output/images/
# rootfs.ext2  rootfs.tar  Image  start-qemu.sh

在真实项目中,工程师往往先基于厂商提供的 defconfig 起步,再逐步裁剪。例如某工业网关需要只读根文件系统以提高掉电安全性,就可以在 Filesystem images 中关闭 ext4、启用 squashfs,并通过 overlay 把只读根与可写数据分区分离。另一个典型场景是快速验证:使用 QEMU 的 qemu_aarch64_virt_defconfig,几分钟内即可得到可启动的根文件系统,用于验证 init 脚本与应用程序。

常见误区与复盘

误区一:把 output/target/ 直接当作可烧录镜像。它只是构建中间目录,缺少设备节点与权限修正,必须经过镜像生成步骤。误区二:修改 output/target/ 中的文件后重新 make,改动会被覆盖。正确做法是使用 overlay 或 post-build 脚本。误区三:忽略 BR2_ROOTFS_OVERLAY 与 BR2_ROOTFS_POST_BUILD_SCRIPT 的执行顺序,导致定制内容被后续步骤覆盖。

为便于后续章节对照,下表列出本课程将反复使用的关键目录与文件:

路径 / 文件 作用 是否可手工修改
configs/ 存放各开发板的 defconfig 可新增,不建议改官方文件
package/ 软件包描述与构建规则 可新增自定义包
board/ 板级 overlay、内核配置、启动脚本 推荐在此定制
output/target/ 根文件系统目录树中间产物 不建议直接改
output/images/ 最终可烧录镜像 只读使用
.config 当前构建的完整配置 由 menuconfig 生成
学习建议:每完成一次配置变更,先执行 make savedefconfig 保存最小配置,再执行 make。这样既能版本化管理配置,也能在构建失败时快速回退。根文件系统的构建不是一次性的,而是“配置—构建—验证—再配置”的迭代过程。

掌握本章的框架后,后续内容将沿着“配置体系 → 工具链 → 内核与引导 → 根文件系统组成 → 镜像格式 → 定制与优化 → 故障排查”的路径逐步展开。每一章都会落到具体的配置项、命令与产物上,最终形成一套可复用的嵌入式根文件系统构建方法。