Linux根文件系统挂载流程

根文件系统是Linux从内核控制转向用户空间的关键,它通过init程序实现这一转换。文章介绍了根文件系统的基本概念,包括initramfs和initrd的作用。内核通过加载过渡根文件系统(如initramfs、initrd)来处理不同存储介质的驱动,然后挂载实际的根文件系统。挂载流程涉及内核初始化、过渡文件系统的解析、检查初始化程序以及挂载实际根文件系统。文章还讨论了不同情况下是否需要使用过渡根文件系统,并提到了不同类型的init程序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

根文件系统的概念

根文件系统是控制权从linux内核转移到用户空间的一个桥梁。linux内核就类似于一个黑匣子,只向用户提供各种功能的接口,但是功能的具体实现不可见,用户程序通过对这些功能接口的不同整合实现不同的功能需求。以用户的角度来说,应用程序调用内核的接口实现不同的功能,此时系统的控制权在用户手中,但是实际上却是先有内核的初始化提供这些接口,用户才可以使用这些接口的,也就是系统的控制权最初应该属于内核。那么控制权是如何从内核转交到用户的呢?通过调用init程序实现,而一般把存在init程序的文件系统称之为根文件系统。

文件系统是基于物理存储设备至上的一种机制,用于存储空间的管理,并维护文件内容与磁盘单元之间的对应关系,便于对文件内容的访问。由前面所述,init程序存储在文件系统之中,如果需要访问init程序必须能够识别对应文件系统的格式(通过挂载实现),而文件系统又建立在物理存储设备之上,所以需要物理存储设备的驱动程序已准备就绪。

文件系统的挂载需要提供挂载点(挂载目录),linux内核在初始化时会初始化一个虚拟的“/”目录用于根文件系统的挂载,其初始化过程如下:

start_kernel
	vfs_caches_init()
		mnt_init()
			init_rootfs()
				register_filesystem(&rootfs_fs_type)						//注册虚拟的rootfs文件系统
			init_mount_tree()												//创建“/”目录
		bdev_cache_init()
		chrdev_init()
	rest_init()
		kernel_thread(kernel_init, NULL, CLONE_FS)
		kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);

initramfs和initrd

若init程序存在的物理磁盘设备在内核访问时已准备就绪,内核便可以直接挂载根文件系统并运行init程序,实现kernel空间到用户空间的跳转。但是用户程序可能根据不同的需要存储在诸如IDE、SCSI、USB等多种介质当中,如果将所有的驱动程序都编译进内核,将导致内核异常臃肿,因此,为了使内核适应不同的存储介质,同时不将非必要的驱动程序编译进内核,可使用一种过渡根文件系统。过渡根文件系统与linux内核存放在同一个存储设备中,因此可以直接挂载,而此时该文件系统中的init程序只是加载实际根文件系统的驱动和其他的一些初始化工作,待初始化完成,该init程序会挂载实际的根文件系统,并再次跳转到实际根文件系统中执行实际的init程序。

过渡的根文件系统根据是否直接编译进内核分为initramfs和initrd,而initrd根据文件系统的打包格式又分为cpio-initrd和image-initrd,通过cpio打包的文件系统可以直接释放到“/”,而无需挂载过程,initramfs也是cpio的打包格式。

根文件系统的整体挂载流程如下图所示:
在这里插入图片描述
首先,内核根据配置利用过渡根文件系统或默认设置初始化“/”目录;然后检测初始化的“/”目录中是否存在指定应用程序(默认为init程序),如果存在,则直接执行该init程序;否则,根据配置挂载实际根文件系统。与之对应的函数流程为:

kernel_init
	kernel_init_freeable()
		do_basic_setup()
			do_initcalls()
				do_initcall_level(level) 										
[1]					do_one_initcall
		
		if (!ramdisk_execute_command)										//如果没有定义rdinit参数,则默认执行rootfs中的/init程序
			ramdisk_execute_command = "/init";
		
[2]		sys_access((const char __user *) ramdisk_execute_command, 0)		//查看rootfs是否有/init程序,若包含则直接运行,否则运行prepare_namespace
			ramdisk_execute_command = NULL;									//并将ramdisk_execute_command置为NULL
[3]			prepare_namespace()
																			//此时已经处于实际根文件系统的目录下
	if (ramdisk_execute_command) {											//首先尝试运行rdinit=指定的程序
  		run_init_process(ramdisk_execute_command);
	
[4]	if (execute_command)  													//再尝试运行init=指定的程序
		run_init_process(execute_command)

	if (!try_to_ru
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值