在/boot目录下,一般都有一个/boot/initrd.img文件或一个/boot/initramfs.img文件,但是要看里面的内容还得有点技巧。先得学习一下历史。第一个问题就是为什么要有 initrd 或者 initramfs,答案是这样的,为了减小 Linux 内核的大小,有一些驱动并没有编译进内核,而是以模块的形式存在于文件系统中,但是有些文件系统呢又需要内核加载了相应的驱动模块才能读取,这样就形成了一个是先有鸡还是先有蛋这样的一个矛盾的问题,为了解决这个问题,就是把这些驱动模块放到 initrd 或 initramfs 文件中,由启动器���其载入内存,然后内核加载内存中的驱动模块,再驱动其它的文件系统,然后进行更多的工作。同时,对于很多嵌入式操作系统而言,可能载入内存的 initrd 或 initramfs 就是最终的文件系统。第二个问题就是 initrd 文件和 initramfs 文件是什么格式的,怎么创建和打开。这个问题有点复杂,且看我下面细细道来。
其实在 Linux 的历史中,内存中的文件系统使用的技术还不一样。在很老的系统中,是将某一块内存模拟成磁盘,称之为 RamDisk,这个技术效率不高,为什么不高呢,那是因为将内存模拟成磁盘后,依然需要像对待磁盘一样对待它,需要给它创建特定格式的文件系统,读取或写入文件的时候还是要用到内核的缓存系统,这样同一份数据就在内存中存在了两份,所以很浪费。老系统中使用的 initrd 文件其实就相当于是一个磁盘的镜像,所以要读取或写入它的内容,就需要将它挂在到系统中,然后进行读写。
现在我们用的都是新系统,initrd 已经被 initramfs 取代了,虽然很多系统中仍然用initrd.img作为文件名,其实使用的是 initramfs 技术。initramfs 技术不使用 RamDisk,而是使用 tempfs,也就是复用了内核中的缓存系统,所以 tempfs 中的内容在内存中只存在一份,那就是在内核的缓存中,不仅节约了内存开销,也提高了效率。那么 initramfs 文件是什么格式呢?它就是经过压缩的 CPIO 格式,只要会cpio,打开它就不是问题。
其实也不是完全没有问题,我在研究 Fedora 21 的 initramfs.img 文件时就碰到了困难。如果大家使用cat initramfs.img | cpio -imd将该 CPIO 文件解开,会发现只有少许几个文件,文件数量和文件大小都远远低于我们的预期,如下图:
问题究竟出在哪里呢?这是因为 Fedora 21 采用了最新的 Early User Space 技术。这个问题在网上还暂时搜不到答案,我也是看到解压出的文件中有一个early_cpio,然后以 early 为关键词去看内核的代码,才知道的。但是关于该技术的具体信息,我也没搞懂。不过这不是重点,重点是如何正确地将该文件解包。首先,我找到了 Fedora 21 系统中用来构建 initramfs 文件的工具是 dracut,采用的方法论请看我该系列的第一篇,如下图:
然后,我发现 dracut 软件包中提供的lsinitrd工具可以查看 initramfs 中的内容,而且该工具是一个脚本。所以我就把它打开看了一下,如下图:
在这个脚本中,我发现它需要用到一个skipcpio程序,跳过 initramfs 文件的头部后,再将剩下的部分当成压缩的 CPIO 文件进行解包。看来,会读脚本程序有时也很重要,所以我的《Bash脚本编程语言中的美学与哲学》这一篇没有白写。最后,解包 initramfs 文件的命令是这样的:
sudo /usr/lib/dracut/skipcpio initramfs-$(uname -r).img | zcat | cpio -imd 如下图:
接下来,我们就可以愉快地研究/init程序都干些什么了。