首先要知道文件系统的意义,文件系统实际上就是存储设备上的数据或源数据按照某一种方式进行组织和管理的机制,
按照这种方式利于用户和操作系统进行交互,如linux对nandflash和norflash都抽象了mtd设备,然后再在上层建立适合
的文件系统,各自的文件系统又统一在VFS下,VFS对用户提供统一的访问接口。
根文件系统,也是一种文件系统,除了一般的存储数据外,特殊之处是内核启动时挂载mount的第一个文件系统,包括
了内核的映像文件,系统引导程序在根文件系统挂载后,会将其中的一些初始化脚本和服务(如rcS,inittab)加载到内存中去。
根文件系统挂接过程:现将dev/ram0挂载,而后执行/linuxrc.等其执行完毕后,切换根目录,然后mount 根文件系统。接着是内核函数
start_kernel,最后执行第一个用户进程init进程。
具体分析:
kernel的发展趋势是讲更多的功能放到用户空间完成,rootfs分为虚拟和真实的,虚拟rootfs是各linux发行商普遍采用的一种方式,
将一部分初始化工作放到虚拟的rootfs中完成,然后切换到真实的文件系统中。
虚拟的rootfs也有几个版本:initramfs,cpio-initrd,image-initrd。下面只讨论initrams(kernel2.5引入)。分析基于内存的rootfs
文件系统,指的是系统初始化时的根节点,即/结点。initramfs是指在内核镜像中附加一个cpio包,这个cpio包中包含了一个小型的文件系统,
当内核启动时,内核将这个cpio包解开,并将其中包含的文件系统释放到rootfs中。
init_rootfs首先注册根文件系统,init_mount_tree将rootfs在默认挂接点"/"下挂接,最后切换进程的根目录和当前目录为
“/”。上述完成根目录挂接后,就可以挂接具体的文件系统了。
do_basic_setup -- do_initcalls是一个关键的函数,所有直接编译在kernel中的模块都是由它启动的。do_initcalls用来
启动所有在__initcall_start和__initcall_end段的函数,静态编译的内核modules也会将其入口放置在这段区间里。与根文件
系统相关的初始化函数都会由rootfs_initcall所调用,rootfs_initcall(populate_rootfs)。populate_rootfs中有一个函数
unpack_to_rootfs,就是解压包,将其释放至rootfs(除了释放包之外,还可以查看报的属性),如果是跟kernel融为一体的
initramfs,那么在编译内核时,通过链接脚本将其存放在__initramfs_start至__initramfs_end区域,这样unpack_to_rootfs
将其释放到根目录下。如果不是initramfs格式的,那么这一段空间长度是0,不做处理。
接下来内核初始化过程中,ramdisk_execute_command在kernel解析引导参数时使用,如果用户指定了init文件路径,就将
这个参数值存放到"init=",如果没有指定init文件路径,默认为/init。对于initramdisk和cpio-initrd的情况,都会将虚拟根文件系统
释放到根目录,如果这些虚拟文件系统中又/init这个文件,就会转入到init_post()。init_post就会执行/sbin/init, /etc/init, /bin/init, /bin/sh。
run_init_process("sbin/init"),run_init_procwss使用的是kernel_execve,也就是调用进程会替换当前进程,只要有一个文件
调用成功,就不会返回到这个函数。
对于image-hdr或者是虚拟文件系统中没有包含/init的情况,会由prepare_namespace()处理。用户可以用root=来指定根文件系统,
它的值保存在saved_root_name中,如果用户指定了以mtd开始的字串作为它的根文件系统,就会直接去挂载,这个文件就是mtdblock的
设备文件。
参考: http://blog.csdn.net/nancygreen/article/details/5027039