空间给内存盘,并进行校验计算,解压缩,最后将内存盘镜像加载到内存中。此时,你就已经拥有了一个适合于挂载的,在块设备中的initrd镜像。
现在,通过调用init/do_mounts.c:mount_root()将这个块设备做为root挂载。ok,根设备就被创建了,接下来调用的函数是init/do_mounts.c:mount_block_root(),此函数又调用fs/namespace.c: sys_mount()来挂载真实的根文件系统并对其进行chdir操作。
最后,会返回到启动函数中,并调用init/main.c:run_init_process。调用的结果是,初始化进程开始(在这里是通过/linuxrc)。linuxrc可以是一个可执行程序,也可以是脚本(只要脚本解释器能够正常解释它)。
函数调用的层次关系可以从下表中看出。并不是所有与复制、挂载初始化内存盘的函数都被列举出来,这里仅仅是大概的,对整体基本流程的回顾:
init/main.c:init
init/do_mounts.c:prepare_namespace
init/do_mounts_initrd.c:initrd_load
init/do_mounts_rd.c:rd_load_image
init/do_mounts_rd.c:identify_ramdisk_image
init/do_mounts_rd.c:crd_load
lib/inflate.c:gunzip
init/do_mounts.c:mount_root
init/do_mounts.c:mount_block_root
init/do_mounts.c:do_mount_root
fs/namespace.c:sys_mount
init/main.c:run_init_process
execve
无盘启动的应用
同很多嵌入式系统的启动一样,本地磁盘(软驱或者光驱)对于启动内核和内存盘根文件系统来说,并不是必须的。DHCP工具能被用于确认网络参数,例如大家熟悉的IP抵制和子网掩码等。此外,TFTP能被用于将内核镜像以及初始化内存盘镜像传送到本地设备。一旦传输完成,linux内核就能被启动以及挂载 initrd,和本地镜像启动的过程一样。
让你的initrd尽可能小
当你在构建嵌入式系统时,总是希望initrd的镜像尽可能小,恩,这里将提供一些小技巧。首先就是使用BusyBox。前面已经提到过,BusyBox包含了很多较大的工具,通常体积都以MB计算,但是它成功得将自己的体积控制在几百KB的范围内。
在本例中,BusyBox镜像使用的是静态链接,因此不需要提供任何库文件。但是,如果你需要得到标准的C库文件来满足自己的二进制程序,除了大体积的 glibc库,你有其他更好的选择。第一个,小体积的uClibc库,是专门用于有空间限制的,标准C库的缩水版本。另一个适用于有空间限制环境的库是 dietlib。记住,你需要在自己的嵌入式系统中,用这些库重新编译你的二进制程序。虽然使用它们会带来一些附加的工作,但是,是值得的。
总结
初始化内存盘技术被创建的最初目的,是为了让内核通过一个临时的根文件系统来过渡到最终的根文件系统。initrd对于嵌入式linux系统同样是很有用处的:它能做为一个非持续性的根文件系统挂载到内存盘中。