1. 课程导入
当你把 Linux 内核成功编译并烧写到开发板后,串口终端往往会停在最后一行:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)。这不是内核编译失败,而是内核找不到可以挂载的根文件系统。嵌入式 Linux 系统由三大部分组成:Bootloader(如 U-Boot)、Linux 内核、根文件系统。前两者负责“把系统启动起来”,而根文件系统负责“让系统真正可用”。本课程围绕第三部分展开,目标是让你能够独立构建、裁剪、打包并调试一个可量产的嵌入式 Linux 根文件系统。
1.1 什么是根文件系统
根文件系统(Root File System,简称 rootfs)是内核在启动末期挂载的第一个文件系统,挂载点为 /。它并不是一个“普通文件夹”,而是一套符合 FHS(Filesystem Hierarchy Standard)规范的目录树,包含系统运行所需的全部用户空间内容:
- /bin、/sbin、/usr:可执行程序与系统命令,如
sh、ls、ifconfig。 - /lib、/usr/lib:动态链接库,如
libc.so.6、ld-linux.so.3。 - /etc:配置文件,如
inittab、fstab、passwd。 - /dev:设备节点,由
devtmpfs或mdev/udev动态生成。 - /proc、/sys:内核虚拟文件系统挂载点,用于查看和配置内核状态。
- /root、/home、/tmp、/var:用户数据、临时文件与运行时数据。
内核启动的最后一步是执行 /sbin/init(或通过 init= 参数指定),这个进程就是用户空间的“第 1 号进程”,它读取 /etc/inittab 或 systemd 配置,拉起登录 shell、网络服务、应用程序。因此,根文件系统是内核与应用程序之间的“桥梁”。
1.2 根文件系统的作用与核心原理
从系统启动链路看,根文件系统承担四个关键职责:
- 提供 init 进程:内核通过
kernel_init调用execve("/sbin/init"),若该文件不存在则 panic。 - 提供动态链接环境:绝大多数用户程序依赖 glibc/uClibc/musl,缺少
/lib/ld-*.so会导致No such file or directory。 - 提供设备与配置:
/dev/console、/etc/fstab、网络配置等决定系统能否正常交互。 - 承载应用与数据:业务程序、脚本、数据库、OTA 升级包都存放在 rootfs 中。
常见的根文件系统形态包括:ramdisk/initramfs(内存中解压,启动快、掉电丢失)、Flash 上的只读文件系统(squashfs、cramfs,适合固件)、可读写文件系统(jffs2、ubifs、ext4,适合需要保存配置的场景)、网络文件系统 NFS(开发调试阶段最常用)。选择哪种形态,取决于存储介质、启动速度、可靠性和可维护性要求。
1.3 整体知识框架与学习路径
本课程共 30 章,按“概念—构建—裁剪—打包—调试—量产”的主线推进。下图展示了根文件系统在嵌入式 Linux 启动链路中的位置,以及本课程的知识结构:
学习路径建议按以下顺序推进:先理解内核如何寻找并挂载 rootfs,再手工制作一个最小可启动的目录树,接着用 BusyBox 替换臃肿的 GNU 工具集,然后学习不同文件系统镜像的打包方式,最后通过 NFS 调试和启动日志分析定位问题。每一章都会给出可复现的命令和配置。
1.4 典型场景与常见误区
在实际项目中,根文件系统问题往往表现为“内核起来了但系统不能用”。下表列出常见现象与根因,便于你在后续章节中对照排查:
| 现象 | 可能根因 | 排查方向 |
|---|---|---|
| Kernel panic: VFS Unable to mount root fs | 内核未配置对应文件系统驱动,或启动参数 root= 错误 | 检查 CONFIG_BLK_DEV_INITRD、bootargs |
| init: not found | 缺少 /sbin/init 或动态链接库 |
用 file、readelf -d 检查依赖 |
| 登录后命令全部 command not found | PATH 未设置或 BusyBox 未创建符号链接 | 检查 /etc/profile 与 busybox --install |
| 系统启动后无法保存配置 | rootfs 为只读 squashfs,未挂载可写分区 | 规划 /data 或 overlayfs |
| NFS 挂载超时 | 内核未启用 NFS root,或网络参数不匹配 | 检查 CONFIG_ROOT_NFS、ip= 参数 |
/bin、/lib 到开发板。PC 使用 glibc 且指令集不同,必须使用交叉编译工具链生成的目标平台库和程序。误区三:忽略 /dev/console 和 /etc/inittab,导致串口无输出、无法登录。
1.5 本章小结与实操准备
根文件系统是嵌入式 Linux 的“用户空间地基”。它决定了系统启动后能提供哪些命令、库、服务和配置。本课程将带你从零开始,逐步完成一个可启动、可裁剪、可量产的 rootfs。开始后续章节前,请确认你的开发环境已具备以下工具:
# 建议的宿主环境(Ubuntu 20.04/22.04)
sudo apt install build-essential git bison flex libncurses-dev \
libssl-dev u-boot-tools device-tree-compiler \
gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
# 验证交叉工具链
arm-linux-gnueabihf-gcc -v
# 准备一个可用的串口终端
sudo apt install minicom picocom
picocom -b 115200 /dev/ttyUSB0