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 命令集成到一个可执行文件中,通过符号链接或硬链接的方式,让同一个二进制文件根据调用名执行不同功能。这种设计带来三个直接收益:
- 体积小:一个 BusyBox 二进制通常只有几百 KB,远小于分别编译 coreutils、util-linux、iproute2 等工具集的总和。
- 可裁剪:通过 menuconfig 可以按需选择命令,去掉不需要的功能,进一步压缩体积。
- 可静态链接:支持静态编译,避免依赖外部动态库,特别适合 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 二进制 | 启动后提示 “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 降低了工具集的构建难度,但并没有消除系统集成的复杂性。真正决定成败的,是对启动流程和文件系统结构的理解深度。