本文旨在深入探讨Linux根文件系统的本质与启动流程。一个常见的理解是,根文件系统是内核启动后挂载的第一个文件系统,是文件树的根。然而,从内核的视角来看,这个说法可以进一步精确。我们将基于Linux内核6.10版本,剖析根文件系统的真实构成。
1. 根文件系统从何而来?
用户通常接触到的“根文件系统”,实际上是挂载在根目录 (/) 下的一个真实的文件系统,如 ext4 或 xfs,我们可称之为真实根文件系统。然而,在内核初始化时,首先挂载的是一个名为 rootfs 的文件系统。rootfs 是一个伪文件系统,仅存在于内存中,它才是Linux启动后第一个被挂载的文件系统,是真正的“根”。
从内存中的 rootfs 过渡到磁盘上的真实根文件系统,主要经历三个步骤:
- 挂载
rootfs 伪文件系统。
- 解析
initramfs 到 rootfs。
- 挂载真实根文件系统(如ext4)。

图1:真实根文件系统挂载流程
首先分析 rootfs 的挂载。rootfs 的文件系统类型定义如下:
struct file_system_type rootfs_fs_type = {
.name = “rootfs”,
.init_fs_context = rootfs_init_fs_context,
.kill_sb = kill_litter_super,
};
查看 rootfs_init_fs_context 函数:
static int rootfs_init_fs_context(struct fs_context *fc)
{
if (IS_ENABLED(CONFIG_TMPFS) && is_tmpfs)
return shmem_init_fs_context(fc);
return ramfs_init_fs_context(fc);
}
由此可见,rootfs 本质上是一个 tmpfs 或 ramfs 文件系统的实例。这两者都是基于内存的文件系统,数据存储在RAM中,读写速度快,但系统重启后数据会丢失。
内核启动函数 start_kernel() 会执行一系列初始化,其中 rootfs 的初始化路径为:start_kernel() -> vfs_caches_init() -> mnt_init() -> init_mount_tree()。init_mount_tree 函数会创建 rootfs 的挂载实例和根目录,并将信息记录在内核。这解决了Linux文件树“从0到1”的问题,rootfs 的根目录即是文件树的起点,后续的真实文件系统都将挂载于此。
有了 rootfs 之后,内核便会解析 initramfs 到其中。initramfs 常被误认为是一种文件系统,实则不然。它是一个经过压缩(如lz4, gzip, zstd)的cpio归档文件,包含了挂载真实根文件系统所需的所有驱动和工具。内核会解析这个归档包,并将其中的文件逐一“填充”到 rootfs 中(可理解为文件拷贝)。解析 initramfs 的路径大致为:start_kernel() -> ... -> do_populate_rootfs()。
解析完成后,rootfs 的根目录下会出现一个关键的 init 脚本。该脚本将负责挂载真实根文件系统,并完成运行环境的切换。执行该脚本的路径为:start_kernel() -> ... -> run_init_process(“/init”)。
2. initramfs详解
initramfs 本质上是 newc 格式的cpio归档文件。cpio是一种用于打包文件和目录并保留元数据(权限、时间戳等)的工具。initramfs 由一条条文件记录构成,每条记录的格式为:
- 文件头(110字节)
- 文件名
- 0-3字节填充(用于4字节对齐)
- 文件数据
- 0-3字节填充(用于4字节对齐)
其中,文件头包含了文件的元数据,其固定格式如下表所示:
表1: newc格式文件头

为了更直观地理解,我们可以创建一个最小化的 initramfs。测试脚本如下:
#!/bin/bash
# 创建文件树
mkdir bin conf etc lib
touch etc/test.txt
# 创建init脚本
echo “#!/bin/sh” > init
# 打包为newc格式
find bin conf etc lib init -depth | cpio -o -H newc > initramfs.cpio
执行脚本生成 initramfs.cpio 后,可用 cpio -t < initramfs.cpio 查看文件列表,或用 hexdump -C 查看其二进制格式。最终,cpio归档中的这些文件记录会被内核解析并存入 rootfs。
3. /init脚本
/init 脚本是 initramfs 的核心,它承担着承上启下的关键任务:
- 挂载
/proc, /sys, /dev 等虚拟文件系统,并创建设备节点。
- 加载必要的存储设备和文件系统内核模块。
- 挂载真实根文件系统。
- 将系统根目录切换到真实根文件系统,并启动
/sbin/init 进程(即1号进程)。
内核调用 run_init_process(“/init”) 执行此脚本,该函数的主要作用是启动用户空间的第一个进程,完成内核态到用户态的切换。
在真实根文件系统(如 ext4)挂载前,所有文件操作都在 rootfs 中进行。/init 脚本首先将 proc、sysfs 等伪文件系统挂载到 rootfs 下。接着,读取块设备,并将设备中的真实根文件系统挂载到 rootfs 的某个目录(例如 /newroot)。最后,将已挂载的伪文件系统移动到新的根目录下,并执行 switch_root 命令彻底切换到真实根文件系统环境。
switch_root 命令的核心功能包括:
- 将指定的目录(已挂载的真实根文件系统)设置为新的根文件系统。
- 执行新根文件系统中的 init 程序(通常是
/sbin/init,可能指向 systemd 或 init)。
- 清理并释放
initramfs 占用的内存空间。
其语法格式如下:
switch_root [-c /dev/console] NEW_ROOT NEW_INIT [ARGUMENTS_TO_INIT]
NEW_ROOT: 已挂载的真实根文件系统路径,如 /newroot。
NEW_INIT: 真实根文件系统中的 init 程序路径,如 /sbin/init。
-c: 可选参数,用于重定向控制台设备。
总结
完整的 Linux 根文件系统启动流程可归纳为三步:首先,挂载内存中的 rootfs 文件系统,建立文件树的初始根目录;其次,解析 initramfs 归档,将其中的工具和驱动文件填充到 rootfs;最后,执行 initramfs 提供的 /init 脚本,由该脚本完成真实根文件系统的挂载与系统运行环境的最终切换。