Linux根文件系统rootfs机制
概述
Linux虚拟文件系统中存在着两个重要的概念:文件系统和挂载点。Linux内核内部维护一棵全局文件文件系统树,在使用文件系统前,需要先将文件系统进行挂载,在此就涉及一个问题:谁来提供最原始的挂载点?为了解决这个问题,Linux在实际切换到磁盘根文件系统之前,会使用rootfs机制构建最顶层的根文件系统,以提供最原始的挂载点。
rootfs机制
rootfs本身是一种基于内存的文件系统,所有的操作都在内存中完成,因而也不需要额外的设备驱动程序的支持。Linux内核在启动时,会首先静态生成rootfs文件系统的相关结构,用于提供最原始的挂载点和根目录,不过这个时候,新生成的根目录下暂时还不包含任何文件。后面内核会基于rootfs构建一个临时根文件系统,并完成早期用户空间的初始化。
当指定根设备的驱动程序完成加载后,内核或init程序(若临时根文件系统提供了init程序)会将根设备上的文件系统挂载到rootfs的特定目录下,并将系统根目录从rootfs切换到根设备上的文件系统,即最终用户所看到的根文件系统。需要注意的是,在完成切换后,rootfs文件系统仍然存在于系统中,只是对于当前进程而言被隐藏了。
rootfs挂载示例
这里我们以Centos系统为例,通过在grub启动选项中添加rd.break=initqueue
参数,可以让系统在加载磁盘根文件系统之前暂停启动,此时我们就可以看到rootfs的真正面目:
rootfs的初始化与挂载
rootfs的目的是为了给其它的文件系统提供一个最原始的挂载点,因此在系统启动初始化阶段中,就需要对rootfs进行初始化。rootfs初始化流程如下图所示:
rootfs的初始化包括两个步骤:
- 调用init_rootfs函数向系统注册rootfs文件系统类型;
- init_mount_tree实现rootfs根目录的建立以及rootfs文件系统的挂载,于是最原始的挂载点和根目录就生成了;并在最后设置设置系统当前进程的根目录和根文件系统为rootfs。
临时根文件系统的构建
上文提到过,rootfs在初始完之后,其提供的根目录还不包含任何文件,内核会基于rootfs构建临时根文件系统。Linux内核构建临时根文件系统有两种方式:使用initramfs机制或者不使用,用户通过内核配置选项CONFIG_BLK_DEV_INITRD
来选择是否启用initfamfs机制。简化的临时根文件系统流程如下:
- 在未配置initramfs机制的情况下:内核会调用default_rootfs自行在rootfs创建必要的目录和文件,并继续后续的启动过程;
- 在配置了initramfs机制的情况下:initramfs机制提供了一个精简的文件系统,其中包含了基本的根目录结构。在用户提供了initramfs时,内核会在启动时将initramfs解压到rootfs中,然后将控制权交给根目录下的init程序(如果initramfs提供了init程序),内核完成启动。
相关参考
- 《Linux内核设计与实现》
- 《深入理解Linux内核架构》