2. 根文件系统基础

在嵌入式 Linux 系统中,内核启动完成后,必须挂载一个根文件系统(Root Filesystem),才能运行用户空间的第一个进程。根文件系统不是“可选项”,而是系统从“内核能跑”走向“应用可用”的关键桥梁。它决定了系统启动后能看到哪些目录、能执行哪些程序、能加载哪些驱动模块,以及设备节点、配置文件、库文件从哪里来。

一、根文件系统的基本概念

根文件系统是挂载在目录树根节点 / 上的文件系统。它至少需要包含 Linux 用户空间运行所必需的基本内容:

  • 目录结构:如 /bin、/sbin、/etc、/dev、/proc、/sys、/lib、/usr、/tmp、/var 等。
  • 可执行程序:如 init、sh、busybox、mount、ifconfig 等。
  • 动态库与配置:如 libc.so、ld-linux.so、/etc/inittab、/etc/fstab、/etc/profile。
  • 设备节点:如 /dev/console、/dev/null、/dev/ttyS0。
  • 虚拟文件系统挂载点:/proc、/sys、/dev 等,用于内核与用户空间交互。

需要特别区分两个概念:根文件系统是运行时挂载在 / 上的文件系统实例;而根文件系统镜像是烧录到存储介质中的静态文件集合,例如 rootfs.ext4、rootfs.jffs2、rootfs.cpio.gz。镜像被内核挂载后,才成为运行时的根文件系统。

二、根文件系统与内核的关系

内核与根文件系统的关系可以概括为“内核提供机制,根文件系统提供内容”。内核负责进程调度、内存管理、设备驱动、文件系统驱动和网络协议栈;根文件系统则提供用户空间程序、配置和运行时数据。两者通过系统调用接口衔接:用户程序通过 open、read、write、ioctl 等系统调用进入内核,内核再通过 VFS 访问具体文件系统。

内核启动的最后阶段会尝试挂载根文件系统。如果挂载失败,内核会打印类似 VFS: Cannot open root device 或 Kernel panic - not syncing: No init found 的错误,系统无法进入用户空间。因此,根文件系统的类型、位置和内容必须与内核配置匹配。

关键匹配点:内核必须包含对应文件系统驱动(如 ext4、squashfs、jffs2、ubifs、nfs)、对应存储控制器驱动(如 MMC、SPI、NAND、MTD),并正确设置 root=、rootfstype=、init= 等启动参数。

三、启动流程中的角色

以典型 ARM 嵌入式 Linux 为例,启动流程如下:

  1. BootROM 加载 SPL/二级引导程序。
  2. U-Boot 初始化内存、存储和网络,加载内核镜像与设备树。
  3. 内核解压、初始化子系统,挂载根文件系统。
  4. 内核执行 /sbin/init 或 /init,进入用户空间。
  5. init 进程根据 /etc/inittab 或 systemd 配置启动服务、登录 shell 和应用程序。

根文件系统在这一流程中承担“用户空间起点”的角色。没有它,内核只能停留在内核态,无法启动任何应用。对于 initramfs 方式,根文件系统被编译进内核镜像,内核启动时直接解压到内存中,适合快速启动和恢复模式;对于块设备方式,根文件系统位于 eMMC、NAND、SD 卡或网络存储上,适合功能完整、可持久化的系统。

嵌入式 Linux 启动流程与根文件系统角色 BootROM / U-Boot 加载内核 + 设备树 Linux 内核 初始化子系统 挂载根文件系统 根文件系统 /bin /etc /lib /dev /proc /sys /usr init 进程 用户空间 服务 / Shell / 应用程序 登录 / 网络 / 业务逻辑 存储介质与根文件系统镜像 eMMC / NAND / SD / NOR / NFS / initramfs ext4 / squashfs / jffs2 / ubifs / cpio.gz 挂载 VFS 虚拟文件系统层 系统调用接口:open / read / write / ioctl / mmap 内核 根文件系统 用户空间 存储介质 挂载/系统调用

四、常见根文件系统类型与选型依据

嵌入式场景中常见的根文件系统类型包括:

类型 典型介质 特点 适用场景
ext4 eMMC、SD、SSD 日志型、可读写、成熟稳定 通用嵌入式设备、需要频繁写文件
squashfs NOR、NAND、eMMC 只读压缩、体积小、启动快 固件只读、配合 overlay 可写层
jffs2 NOR、NAND 日志型、支持擦写均衡 小容量 NAND、传统嵌入式
ubifs NAND UBI 卷、擦写均衡、压缩 大容量 NAND、现代嵌入式
initramfs 内存 内核内置、解压到 RAM 快速启动、恢复模式、无盘系统
NFS 网络 远程挂载、开发调试方便 开发阶段、网络启动

选型时可以从以下维度判断:

  • 存储介质:NOR 适合 jffs2/squashfs,NAND 适合 ubifs/jffs2,eMMC 适合 ext4/squashfs。
  • 读写需求:需要频繁写入选 ext4 或 ubifs;只读固件选 squashfs。
  • 启动速度:initramfs 和 squashfs 启动较快;ext4 需要文件系统检查,可能稍慢。
  • 可靠性:掉电频繁场景优先日志型或带擦写均衡的文件系统。
  • 开发效率:开发阶段常用 NFS 根文件系统,避免反复烧录。

五、案例与常见误区

以一个基于 i.MX6ULL 的工控板为例:存储为 8GB eMMC,系统需要支持日志写入、远程升级和断电保护。最终选择 ext4 作为根文件系统,同时将 /var/log 和 /data 单独分区,避免日志写满根分区。内核启动参数配置为:

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootfstype=ext4 rw rootwait'

常见误区包括:

  • 只烧内核不烧根文件系统:内核启动后找不到 init,直接 panic。
  • 内核未编译对应文件系统驱动:例如内核没有开启 ext4 支持,却使用 ext4 根文件系统。
  • 设备节点缺失:没有 /dev/console,init 无法打开控制台。
  • 动态库路径错误:程序依赖 /lib/ld-linux-armhf.so.3,但根文件系统中不存在。
  • 启动参数与分区不匹配:root= 指向错误分区,导致挂载失败。
排查根文件系统启动问题时,优先查看内核启动日志中的 VFS、init、root= 相关行,再确认存储分区、文件系统驱动和 init 程序是否存在。

理解根文件系统的基本概念、与内核的协作关系、在启动流程中的位置以及常见类型与选型依据,是后续制作 BusyBox 根文件系统、构建 initramfs、配置 NFS 根文件系统和进行系统裁剪的基础。