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 根文件系统的作用与核心原理

从系统启动链路看,根文件系统承担四个关键职责:

  1. 提供 init 进程:内核通过 kernel_init 调用 execve("/sbin/init"),若该文件不存在则 panic。
  2. 提供动态链接环境:绝大多数用户程序依赖 glibc/uClibc/musl,缺少 /lib/ld-*.so 会导致 No such file or directory。
  3. 提供设备与配置:/dev/console、/etc/fstab、网络配置等决定系统能否正常交互。
  4. 承载应用与数据:业务程序、脚本、数据库、OTA 升级包都存放在 rootfs 中。
根文件系统的本质是“内核启动后交给用户空间的第一份运行环境”。它决定了系统能跑什么程序、以什么方式启动、如何与硬件交互。

常见的根文件系统形态包括:ramdisk/initramfs(内存中解压,启动快、掉电丢失)、Flash 上的只读文件系统(squashfs、cramfs,适合固件)、可读写文件系统(jffs2、ubifs、ext4,适合需要保存配置的场景)、网络文件系统 NFS(开发调试阶段最常用)。选择哪种形态,取决于存储介质、启动速度、可靠性和可维护性要求。

1.3 整体知识框架与学习路径

本课程共 30 章,按“概念—构建—裁剪—打包—调试—量产”的主线推进。下图展示了根文件系统在嵌入式 Linux 启动链路中的位置,以及本课程的知识结构:

嵌入式 Linux 启动链路与根文件系统知识框架 Bootloader U-Boot / SPL Linux 内核 zImage / uImage 根文件系统 rootfs / initramfs init 进程 /sbin/init 内核挂载 rootfs → 执行 /sbin/init → 用户空间启动 课程知识框架(30 章主线) ① 概念与规范 FHS 目录结构 启动流程与 init 文件系统类型选型 ② 构建与制作 BusyBox 编译 库与设备节点 inittab / rcS 脚本 ③ 打包与烧写 initramfs / squashfs ubifs / ext4 镜像 U-Boot 启动参数 ④ 调试与量产 NFS 挂载调试 启动日志排障 裁剪与 OTA 升级 学习路径:理解启动链路 → 手工搭建最小 rootfs → 用 BusyBox 裁剪 → 打包镜像 → 上板调试 → 优化与量产 核心目标:能独立交付一个可启动、可维护、可量产的嵌入式 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= 参数
常见误区一:认为“内核编译成功就等于系统能跑”。实际上,内核只负责硬件与进程调度,没有 rootfs 就没有用户空间。误区二:直接复制 PC 上的 /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
建议在虚拟机或独立 Ubuntu 环境中学习,避免污染主机环境。每章操作前先备份上一阶段的 rootfs 目录,便于对比和回滚。遇到启动失败时,优先查看串口完整日志,而不是凭猜测修改配置。