3. 根文件系统概念:什么是根文件系统、VFS(虚拟文件系统)的作用

根文件系统(Root Filesystem,简称 rootfs)是 Linux 内核启动过程中挂载的第一个文件系统,是整个系统文件层次结构的起点。理解根文件系统的本质以及虚拟文件系统(VFS)的抽象层作用,是分析根文件系统挂载失败问题的理论基础。

3.1 根文件系统的定义与核心特征

根文件系统不仅仅是一个存储数据的目录树,它承载了 Linux 系统运行所必需的初始化脚本、动态链接库、内核模块、设备节点以及核心配置文件。没有根文件系统,内核在完成初始化后将无法执行用户空间的第一个进程(通常是 /sbin/init 或 /init),系统启动会在此处卡死。

特征 说明
挂载点 根文件系统挂载在 / 目录,是所有其他挂载点的祖先。
启动依赖 内核必须能够定位并挂载根文件系统,才能执行用户空间程序。
类型多样性 可以是真实的块设备分区(如 ext4、btrfs),也可以是内存文件系统(initramfs/initrd)、网络文件系统(NFS)或虚拟文件系统(如 tmpfs)。
关键内容 至少包含 /sbin/init、/bin/sh、/etc/inittab(或 systemd 单元)、/dev/console 等。
关键概念: 根文件系统 ≠ 根分区。根文件系统是内核视角的“根目录树”,而根分区是存储设备上的一个物理分区。内核通过挂载操作将分区内容关联到根目录树。

3.2 根文件系统的典型目录结构

一个标准的根文件系统遵循 FHS(Filesystem Hierarchy Standard)规范,但嵌入式系统通常会大幅裁剪。以下是最小根文件系统必须包含的目录和文件:

  • /sbin/init — 用户空间的第一个进程(PID 1),负责启动其他服务。
  • /bin/sh — 基本的 shell,用于救援和脚本执行。
  • /dev/console — 控制台设备节点,内核输出日志和交互的通道。
  • /etc/inittab 或 /etc/init.d/rcS — 初始化脚本或配置。
  • /lib — 动态链接库(如 libc.so、ld-linux.so),init 和 shell 运行所依赖。
  • /proc、/sys、/dev — 虚拟文件系统的挂载点(通常由 init 脚本挂载)。
嵌入式提示: 在嵌入式 Linux 中,根文件系统常被构建为 rootfs.cpio.gz(initramfs)或 rootfs.squashfs(只读压缩文件系统),以节省存储空间并提高启动速度。

3.3 VFS(虚拟文件系统)的作用

虚拟文件系统(VFS)是 Linux 内核中的一个抽象层,它位于用户空间的系统调用接口与具体的文件系统实现(如 ext4、FAT32、NFS、procfs)之间。VFS 的核心目标是:让用户空间程序无需关心底层文件系统的具体格式和存储介质。

VFS 的本质: 一个面向对象的文件系统框架,通过定义一组通用的文件操作接口(如 open、read、write、close、readdir),使得所有文件系统都能以统一的方式被访问。

3.4 VFS 的架构与核心对象

VFS 基于四个核心对象模型来抽象所有文件系统:

VFS 对象 数据结构 作用
超级块 struct super_block 代表一个已挂载的文件系统实例,包含文件系统元数据(块大小、操作函数表等)。
索引节点 struct inode 代表一个文件或目录的元数据(权限、大小、时间戳、数据块指针),不包含文件名。
目录项 struct dentry 代表路径名中的一个组件,负责将文件名与索引节点关联起来,是路径解析的核心缓存单元。
文件对象 struct file 代表一个打开的文件实例,包含文件读写位置、访问模式、引用计数等。

下图展示了 VFS 如何将用户空间的系统调用分发到具体的文件系统实现:

VFS 虚拟文件系统架构图 用户空间程序(open/read/write) 系统调用接口(sys_open / sys_read) VFS 通用文件模型 超级块 | 索引节点 | 目录项 | 文件对象 ext4 FAT32 NFS 块设备驱动 块设备驱动 网络设备驱动 SSD / SD卡 U盘 / 硬盘 网络存储服务器 VFS 层屏蔽了底层文件系统和存储介质的差异,用户程序只需与 VFS 接口交互

3.5 VFS 在根文件系统挂载中的关键作用

在根文件系统挂载过程中,VFS 扮演了以下关键角色:

  1. 注册文件系统类型:内核在启动早期通过 register_filesystem() 注册所有编译进内核的文件系统驱动(如 ext4、squashfs、tmpfs)。
  2. 解析根设备参数:内核根据 bootloader 传递的 root= 参数(如 root=/dev/mmcblk0p2)或 initramfs 中的信息,确定根文件系统的设备路径。
  3. 调用具体文件系统的挂载例程:VFS 根据根设备的文件系统类型,调用对应的 mount 方法,读取超级块并构建根目录的 dentry 和 inode。
  4. 建立根目录树:VFS 将挂载的文件系统实例关联到全局的 mount tree 中,设置当前进程的根目录指针 fs->root。
常见失败点: 如果 VFS 无法找到与根设备匹配的文件系统驱动(例如内核未编译 ext4 驱动,但根分区是 ext4 格式),内核会打印 VFS: Cannot open root device 错误并挂起。这是根文件系统挂载失败的典型原因之一。

3.6 根文件系统与 VFS 的关系总结

下表总结了根文件系统与 VFS 在启动过程中的角色差异:

维度 根文件系统 VFS
本质 存储设备上的数据集合(目录、文件、链接) 内核中的软件抽象层
职责 提供用户空间运行所需的文件内容 提供统一的文件操作接口和路径解析机制
启动时序 在 VFS 初始化之后被挂载 内核启动早期初始化,先于根文件系统挂载
失败表现 内核 panic,无法启动用户空间 系统调用返回错误,但内核可能仍可运行
学习建议: 在分析根文件系统挂载失败时,首先要区分是“VFS 找不到文件系统驱动”还是“文件系统驱动无法读取设备数据”。前者通常需要重新配置内核,后者则可能是设备树错误、分区表损坏或存储硬件故障。