2. 根文件系统(RootFS)概念:作用、典型目录结构

根文件系统(Root Filesystem,简称 RootFS)是 Linux 系统启动过程中内核挂载的第一个文件系统。它不仅是系统运行的基石,更是内核从“自举”阶段过渡到“用户态”的关键桥梁。理解 RootFS 的作用与结构,是正确配置内核挂载参数的前提。

2.1 根文件系统的作用

在 Linux 内核启动的后期阶段,内核需要加载第一个用户态进程(通常是 /sbin/init 或 /bin/busybox),并执行系统初始化脚本。这一切都依赖于一个可读写的、包含必要工具和库的文件系统。RootFS 的核心作用可归纳为以下四点:

作用维度 具体说明 关键依赖
进程启动 提供 /sbin/init 或指定 init= 参数对应的可执行文件 内核需找到 ELF 格式的 init 程序
库与工具 提供 C 运行时库(libc)、动态链接器(ld-linux)及基础命令 init 进程依赖 /lib 下的共享库
设备与内核接口 通过 /dev、/proc、/sys 与内核交互 udev/mdev 需要挂载虚拟文件系统
配置与持久化 存放系统配置文件(/etc)和运行时数据 日志、PID 文件、临时文件需要可写空间
关键概念: 内核在挂载 RootFS 之前,只拥有一个临时的 rootfs(基于 tmpfs 的内存文件系统)。真正的 RootFS 挂载成功后,内核会 pivot_root 或 switch_root 将根目录切换到新的文件系统,并执行 init 进程。

2.2 典型目录结构详解

一个标准的 Linux 根文件系统遵循 FHS(Filesystem Hierarchy Standard)规范。在嵌入式系统中,虽然可以裁剪,但以下目录是绝大多数场景下必须保留的:

嵌入式裁剪提示: 如果使用静态编译的 busybox,可以省略 /lib 目录;如果使用 devtmpfs,可以省略 /dev 目录中的静态设备节点。但 /proc 和 /sys 几乎总是必需的。

2.2.1 核心目录功能对照表

目录 全称 作用 启动阶段是否必需
/bin User Binaries 存放用户级基础命令(ls, cp, cat, sh) 是
/sbin System Binaries 存放系统管理命令(init, mount, ifconfig) 是
/etc Configuration Files 系统配置文件(inittab, fstab, passwd) 是
/lib Libraries 共享库和内核模块(libc.so, ld-linux.so) 是(动态链接时)
/dev Device Files 设备节点(console, null, ttyS0) 是
/proc Process Information 虚拟文件系统,提供进程和内核信息 是
/sys System Information 虚拟文件系统,提供设备和驱动信息 是
/tmp Temporary Files 临时文件存储(通常挂载为 tmpfs) 推荐
/var Variable Data 可变数据(日志、缓存、锁文件) 推荐
/usr Unix System Resources 次要层次结构(可独立挂载) 可选

2.2.2 目录依赖关系与挂载顺序

在系统启动过程中,目录的挂载和初始化存在严格的先后顺序。下图展示了 RootFS 中关键目录的依赖关系:

RootFS 目录依赖与挂载顺序 / (RootFS 挂载点) /bin /sbin /etc /lib /dev /proc /sys /tmp /sbin/init (第一个用户态进程) 说明: 1. /bin、/sbin、/etc、/lib 必须在 init 启动前就绪。 2. /proc、/sys、/dev 通常在 init 启动后由 init 脚本挂载,但内核启动时需保证 /dev/console 存在。

2.3 关键目录的启动阶段行为

2.3.1 /dev —— 设备节点

在系统启动初期,内核会尝试挂载 devtmpfs(如果内核配置了 CONFIG_DEVTMPFS),自动创建设备节点。如果未启用,则必须在 RootFS 中静态创建至少 /dev/console、/dev/null、/dev/ttyS0 等关键节点,否则内核无法输出启动信息。

# 手动创建设备节点示例(在构建 RootFS 时)
mknod -m 600 dev/console c 5 1
mknod -m 666 dev/null c 1 3
mknod -m 666 dev/ttyS0 c 4 64

2.3.2 /proc 与 /sys —— 内核接口

这两个目录是虚拟文件系统,不占用磁盘空间。内核在 init 进程启动后,由 init 脚本通过 mount 命令挂载:

# 在 init 脚本中挂载虚拟文件系统
mount -t proc none /proc
mount -t sysfs none /sys
mount -t tmpfs none /tmp
常见错误: 如果 RootFS 中缺少 /proc 或 /sys 挂载点目录,mount 命令会失败。务必在构建 RootFS 时创建这些空目录:mkdir -p /proc /sys /tmp。

2.4 最小 RootFS 目录结构示例

对于嵌入式系统或 initramfs,一个可工作的最小 RootFS 通常包含以下内容:

/
├── bin/
│   ├── sh              # shell(通常为 busybox 链接)
│   └── busybox         # 或静态编译的 busybox 二进制
├── sbin/
│   └── init            # 指向 /bin/busybox 或自定义 init
├── etc/
│   ├── inittab         # init 进程配置文件
│   └── fstab           # 文件系统挂载表(可选)
├── lib/
│   ├── libc.so.6       # C 运行时库
│   └── ld-linux.so.*   # 动态链接器
├── dev/
│   ├── console
│   ├── null
│   └── ttyS0
├── proc/               # 空目录,用于挂载 proc
├── sys/                # 空目录,用于挂载 sysfs
└── tmp/                # 空目录,用于挂载 tmpfs
性能与安全建议: 在嵌入式系统中,建议将 /tmp 和 /var 挂载为 tmpfs,避免频繁写 flash 导致磨损。同时,/proc 和 /sys 的挂载权限应设置为只读(ro)或使用 hidepid=2 等安全挂载选项。

2.5 本章小结

  • RootFS 是内核启动的终点,用户态运行的起点。 没有正确的 RootFS,内核会 panic 并停止启动。
  • 目录结构遵循 FHS 标准,但嵌入式系统可裁剪。 核心目录 /bin、/sbin、/etc、/lib、/dev 是启动必需的。
  • 虚拟文件系统 /proc、/sys 必须在 init 脚本中挂载。 它们提供了用户态与内核交互的唯一通道。
  • 设备节点 /dev/console 是内核输出控制台信息的必要条件。 缺少它会导致启动信息丢失。