1. 课程导入

当我们拿到一块刚出厂的嵌入式开发板,或者完成一次内核移植之后,最先面对的问题往往不是“内核能不能跑起来”,而是“内核跑起来之后,用户能看到什么、能操作什么”。这个问题的答案,就落在 根文件系统(Rootfs) 上。Rootfs 是 Linux 内核启动后挂载的第一个文件系统,它承载了系统运行所必需的命令、库、配置、设备节点和启动脚本。没有 Rootfs,内核即使成功初始化,也只能停在 panic 状态,无法进入用户空间。

在嵌入式场景中,Rootfs 与桌面发行版有本质区别:资源受限、存储介质多样、启动速度敏感、可裁剪性要求高。因此,如何构建一个“够小、够稳、够快”的根文件系统,是嵌入式 Linux 工程师的核心技能之一。而 BusyBox,正是解决这一问题的关键工具。

一、Rootfs 在嵌入式 Linux 系统中的地位

从系统启动链路来看,Bootloader 负责加载内核,内核负责初始化硬件并挂载 Rootfs,Rootfs 中的 init 进程再拉起用户空间服务。三者环环相扣,Rootfs 是连接内核与应用的“最后一公里”。它至少承担以下职责:

  • 提供 init 进程:内核启动后第一个用户态进程,负责系统初始化、服务启动和进程管理。
  • 提供基础命令与工具:如 sh、ls、cp、mount、ifconfig 等,供开发调试和系统运维使用。
  • 提供运行时库:如 glibc 或 musl、libc、libm 等,应用程序依赖这些动态库才能运行。
  • 提供设备节点与挂载点:/dev、/proc、/sys、/tmp 等目录结构是系统正常运转的基础。
  • 提供配置文件:如 /etc/inittab、/etc/fstab、/etc/init.d/rcS 等,决定系统行为。

可以说,Rootfs 是嵌入式系统的“用户空间地基”。地基不稳,上层应用再优秀也无法落地。

二、BusyBox 的核心价值

BusyBox 被称为“Linux 瑞士军刀”,它把数百个常用 Unix 命令集成到一个可执行文件中,通过符号链接或硬链接的方式,让同一个二进制文件根据调用名执行不同功能。这种设计带来三个直接收益:

  1. 体积小:一个 BusyBox 二进制通常只有几百 KB,远小于分别编译 coreutils、util-linux、iproute2 等工具集的总和。
  2. 可裁剪:通过 menuconfig 可以按需选择命令,去掉不需要的功能,进一步压缩体积。
  3. 可静态链接:支持静态编译,避免依赖外部动态库,特别适合 initramfs 或救援系统。

下面是一个典型的 BusyBox 编译配置片段,展示了如何选择命令和链接方式:

make menuconfig
# Busybox Settings --->
#   Build Options --->
#     [*] Build BusyBox as a static binary (no shared libs)
#   Installation Options --->
#     [*] Don't use /usr
# Applets --->
#   Shells --->
#     [*] ash
#   Coreutils --->
#     [*] ls  [*] cp  [*] mv  [*] rm
#   Networking Utilities --->
#     [*] ifconfig  [*] ping  [*] udhcpc

make -j$(nproc)
make install CONFIG_PREFIX=/opt/rootfs

执行完成后,/opt/rootfs 下会生成 bin、sbin、usr 等目录,以及大量指向 busybox 的符号链接。这个目录就是 Rootfs 的雏形。

核心结论:BusyBox 不是“一个命令”,而是“一套命令集合的压缩实现”。它让嵌入式 Rootfs 在有限存储中拥有完整的用户空间工具链。

三、课程学习目标与整体知识框架

本课程围绕“基于 BusyBox 的 Rootfs 定制化实战”展开,目标不是简单罗列命令,而是建立一套可复用的构建方法论。学完本课程,你应当能够:

  • 理解 Rootfs 的目录结构标准(FHS)与嵌入式裁剪原则;
  • 独立完成 BusyBox 的配置、编译、安装与符号链接生成;
  • 构建 init 脚本、inittab、rcS 等启动流程;
  • 制作 initramfs、ext4、ubifs、squashfs 等多种格式的根文件系统镜像;
  • 掌握动态库依赖分析、设备节点创建、权限与用户管理;
  • 能够定位并解决 Rootfs 启动失败、命令缺失、库找不到等常见问题。

整体知识框架可以概括为“一条主线、四个层次”:主线是“从源码到可启动 Rootfs”,四个层次分别是工具层(BusyBox)、结构层(目录与文件)、启动层(init 与脚本)、镜像层(打包与烧录)。下图展示了这一框架的核心关系:

Rootfs 定制化知识框架 从源码到可启动根文件系统的主线路径 工具层 BusyBox 配置与编译 menuconfig / make 结构层 目录与文件布局 /bin /etc /dev /lib 启动层 init 与启动脚本 inittab / rcS 镜像层 打包与烧录 initramfs / ext4 / ubifs 支撑技术 交叉编译工具链 · 动态库依赖分析 · 设备节点管理 · 文件系统格式 · 启动参数与内核配置 主线:源码 → 配置 → 编译 → 安装 → 脚本 → 打包 → 烧录 → 启动验证 每个层次均可独立裁剪与优化,最终目标是“最小可启动、可维护、可量产”

四、常见误区与复盘

初学者在构建 Rootfs 时,最容易踩的坑集中在以下几个方面:

误区 典型表现 正确做法
只复制 BusyBox 二进制 启动后提示 “can't access tty” 或命令找不到 执行 make install 生成完整符号链接和目录结构
忽略动态库依赖 运行命令时报 “not found” 但文件明明存在 用 readelf -d 或 ldd 检查依赖,复制对应 .so 到 /lib
init 脚本权限错误 内核 panic: “No init found” 确保 /init 或 /sbin/init 有可执行权限,且解释器路径正确
设备节点缺失 无法打开 /dev/console 或 /dev/null 用 mknod 创建 console、null 等必要节点,或使用 devtmpfs
文件系统格式不匹配 内核无法挂载 Rootfs,提示 “VFS: Cannot open root device” 确认内核已编译对应文件系统驱动,且启动参数 root= 正确

排障提示:当 Rootfs 启动失败时,优先检查内核启动日志中的最后几行。常见关键字包括 “No init found”、“Unable to open initial console”、“VFS: Cannot open root device”。这三类错误分别对应 init 缺失、设备节点缺失和文件系统/启动参数问题。

复盘这些误区可以发现,Rootfs 构建不是“把文件拷进去”那么简单,而是一个涉及工具链、库依赖、权限、设备模型和内核配置的系统工程。BusyBox 降低了工具集的构建难度,但并没有消除系统集成的复杂性。真正决定成败的,是对启动流程和文件系统结构的理解深度。