首先是我个人对根文件系统挂载的一些看法。
所谓挂载,我认为,就是在已经注册(初始化)好的vfsmount结构体中加入设备信息,并将设备中的各种结构包括superblock、inode、dentry等加入到vfsmount中。而vfsmount可以看做是特定的file_system_type的一个实例。
而根文件系统挂载在根节点上,并且包含一些init进程必须的文件,为的是为init的运行提供保证。
使用虚拟根文件系统的目的是为真实的根文件系统的挂载提供条件。使用虚拟根文件系统,而不是使用start_kernal中完成这些必须的初始化,是为了保持内核的一致和精简,将更多的与内核关系不大的工作放到用户空间执行。
这些看法如果有不对的希望各位留言指正或者补充,THX。
1、VFS注册
2、VFS挂载
3、根文件系统的挂载
default_rootfs()主要往rootfs中生成两个目录/dev和/root以及一个设备文件/dev/console。似乎在rootfs中的init文件必须位于根目录下,即/init,否则系统会尝试mount其他的文件系统。
populate_rootfs()如果内核支持initrd,但并没有配置CONFIG-INITRAMFS_SOURCE选项的话,内核在编译的时候会自动生成一个最小的cpio包附在内核中,这个自带的cpio包的内容与default_rootfs生成的一样。
cpio包类型的initrd被填充到rootfs中去,接下来初始化ramdiak_execute_command,这个变量表示在cpio包中被执行的第一个程序,可通过在内核启动参数中给rdinit=赋值来确定。接下来检查在rootfs中是否存在变量ramdisk_execute_command所指的文件。如果有,就说明cpio包类型的initrd成功加载了,那就不需要内核再调用prepare_namespace()来挂载根文件系统,这些都留给cpio包中的ramdisk_execute_command所指的程序去完成。如果没有,就说明内核没有成功用上cpio包类型的initrd,还需要调用prepare_namespace()来继续准备加载根文件系统,并清空变量ramdisk_execute_command。无论怎样,内核都会继续执行init_post.
在init_post中调用run_init_process,会依次执行指定的init文件,如果失败,就会执行/sbin/init, /etc/init,, /bin/init,/bin/sh。注意的是,run_init_process在调用相应程序运行的时候,用的是kernel_execve。也就是说调用进程会替换当前进程。只要上述任意一个文件调用成功,就不会返回到这个函数。如果上面几个文件都无法执行。打印出没有找到init文件的错误。
源地址:http://blog.sina.com.cn/s/blog_67e2ef6a0100s8kf.html