最近在着手给Sparrow设计一个简单的ram文件系统,想借鉴一下Linux的思路。发现对initrd和initramfs两个概念搞不太清楚,恍惚觉得它们也都是内存文件系统,但又说不清楚其间的区别。今天特意查了一下,做个总结。
的确,它们的相同之处在于,都是用于内核启动阶段的临时内存文件系统。比较一下,主要有这样几点区别:
1. Initrd本身是一个ram disk,是一个虚拟盘的概念,被挂载到设备目录(dev/ram0);initramfs本身就是一种文件系统,直接被作为临时根目录挂载。
2. Initrd由于是设备的概念,所以需要另外的文件系统来管理文件,它依赖于ext2文件系统;而initramfs有自己的文件系统格式CPIO。
3. 挂载好之后,内核首先执行的文件不同。对于Initrd,内核先执行/linuxrc;对于initramfs,行执行/init。
总的来说,initramfs比initrd先进一些,前者是后者的替代品。
这里有一篇比较好的介绍两者区别的文章(http://blog.linux.org.tw/~jserv/archives/001954.html),不过好像这个网站不太稳定,所以把主要的内容节选出来,作为记录:
自 1991 年 Linux ��世以�恚��Y�技�g的��用有了�O大的�D�,�P者之前的文章 [探索 Linux bootloader 的佳作] �c [kboot 初探�c模�M��C] �s略提及光是�_�C本身的�O��碚f,就有多�N�n�襞c需求,�S著 Linux 走出��人��X�I域,在嵌入式系�y��用上,更是五花八�T。本文所探�的 initramfs,衍生自 Linux kernel 的 initrd,理解其�O�需求是先行的��洹�initrd 字面上的意思就是 "boot loader initialized RAM disk",�Q言之,�@是一�K特殊的 RAM disk,在�d入 Linux kernel 前,由 boot loader 予以初始化,具�w�幼骶褪�奶囟ǖ�Υ嫜b置中�d入 initrd 到 RAM 中 (由����� "initrd=" 指定 image 的���w或��位置),�S後 linux kernel 被�d入�K�绦�r,����先�理置放 initrd 的����w空�g,而�@��空�g基本上也有�n案系�y,通常��包含 init 等程式,故可用以�烊肽承┨�e的��映淌剑�比方�f SCSI,完成�A段性目�酸幔�kernel ���⒄嬲�的 root file system �燧d,�K�绦� /sbin/init 程式。
��f回�恚�我���楹涡枰�此等迂�的�_�C途�侥兀吭�因是,root file system (由����� "root=" 所指定,以下��Q rootfs) 所在的�Υ嫜b置很可能�O�y�ふ遥�比方�f SCSI �b置就需要�}�s且耗�r的程序,若用 RAID 系�y更是需要看配置情�r而定,同�拥���}也�l生在 USB storage 上,因�� kernel 得花上更�L的等待�c配置�r�g,或�f�h端�燧d rootfs,不�H得�理�W路�b置的���},甚至�得考�]相�P的伺服器�J�C、通�往返�r�g等�h�}。更重要的是,我��可在 initrd 放置某些特�e的程式,一�碜��燧d rootfs 作��洌�比方�f硬�w初始化、解密、解�嚎s等等,二�硖崾臼褂谜呋蛳到y管理�T目前的��B,�@��於消�M性�子�a品�碚f,有很大的意�x。整�w�碚f,如果能增加�_�C的��性 (比方�f配合��蔚� shell script 即可�_成 USB/SCSI 初始化�幼鳎�若透�^ kernel code ��做,恐怕上百千行是免不掉的),又能�m度降低 kernel image 本身的�O��}�s度�c空�g使用量,�袢� initrd 是很不�e的方式,所以�缀醺鞔� Linux distribution 都有提供 initrd,以解�Q在不同硬�w、不同�b置上�_�C的技�g�h�},也能�_保一片 CD-ROM/DVD 可�b入多�N��人��X系�y,也可支援 [bootsplash] 一��@示�_�C�赢�的程式。
具�w�碚f,initrd 提供了「�呻A段�_�C」程序。首先,一切都�是在 kernel mode,由 kernel 完成�c硬�w相�P的初始化工作,接著,在�m��的�r�C�c,�� kernel �x取�K�燧d initrd 所在����w空�g的�n案系�y後,kernel 首次�� kernel space 切入 user space,以�绦写娣澎� RAM disk 中的 init 程式,��然,�@需要完整的�绦协h境 (比方�f C runtime 或必要的 program loader 等),另外,也得�_定 rootfs 可被 kernel 所找到�K正�_�燧d。待第一�A段的 initrd 步入尾�後,再回到 kernel mode,initrd 所在的����w空�g也���m度被�放 (依���M�B而定),�@才�M入第二�A段,也就是�绦姓嬲�的 rootfs 中的 init 程式。在 Linux kernel 2.4 中,initrd 大致的�理流程如下:(方括�表示主要的�绦�卧�)
值得一提的是,以上「�呻A段�_�C」是 initrd 提出的��性�_�C流程,在真��的��用中,也可能�奈葱枰��燧d真正的 rootfs,�Q言之,只是把系�y��作都在 RAM disk 上�\作,或者永�h都在 initrd 所引��绦械� /linuxrc 程序中�绦� (注意:kernel 永�h保留 PID=1 作�� init process �R�e,而 /linuxrc �绦械� PID 必非�� 1),在�S多�b置如智慧型手�C,都是行之有年的,不�^�@不影�我��後�m的探�。
Linux Kernel 的�l展文化就是�意���既有��做,大��裼眯碌耐�� (在符合���H�格的前提下),Linux 2.6 的 initramfs 之所以提出,就是要修正 initrd 的�N�N技�g���}。���}在哪呢?首先,回�����探�的流程,initrd RAM disk �� kernel �碚f,本身是��真��的 block device,�榱私��存放其中的�n案 (最起�a要有 /linuxrc),通常我��需要 ext2 一�的�n案系�y (建�h)。所以,就建��如此的 initrd image �砜矗�通常��透�^ mkfs.ext2 �c losetup (功能:"set up and control loop devices") 等工具建立 loopback device �K�修,所以自然需面�σ韵���}:
Kernel 文件 ( Documentation/filesystems/ramfs-rootfs-initramfs.txt ) 更指出:
基於上述�Y源使用�c效能考量,原本 ramdisk 途�骄捅�耸�椤咐吓f」,而 initramfs 的提出,�t是基於更��斡行�率的 ramfs �c新的�理方式。
回到 initrd ramdisk,事��上,原本的�O�甚至更加浪�M����w,因�� Linux 在�O�上就���M可能�⒆x入/��入自 block device 的�n案或目�予以 cache,所以,Linux ��自 ramdisk 中�}�u�Y料到 page cache �c dentry cache,如此往返,徒增�Y源使用的浪�M,�@一切���}的根源就是�� initrd 以 block device �聿僮鞯谋举|使然。Linus Torvalds �榇颂岢鲆��想法:
基於�@些想法,Linus Torvalds ��做了 ramfs,�S後在其他核心�_�l者的改�M下,成�� tmpfs,支援��入 swap 空�g�c限制����w使用量等特徵。而,initramfs 就是建��於 tmpfs 的基�A上。�袢〈送�降男б婢褪牵��n案系�y可自行�{整空�g使用量,以符合所需�Y料�Υ娴目臻g,同�r,也不再��有重�}的 block device �c cache �Y料,因�楦�本不需要,更重要的是,�@�拥�n案系�y��做,其��就只是 cache �C制的延伸,�]有太多新的程式�a,所以系�y可保持��蚊�拧R韵率�� initrd �c initramfs 的概念性比�^:
INITRD | INITRAMFS | |
---|---|---|
Image | �嚎s�^的�n案系�y (如 ext2 gzip) | 封�b�^的�n案 (cpio gzip) |
��做途�� | block device (RAM disk) | tmpfs |
首先�绦械某淌� | /linuxrc | /init |
�燧d rootfs 方式 |
�⒂��d入的 rootfs �燧d於某��目�,再 pivot_root 切�Q rootfs | 使用 switch_root |
前面的段落已�f明�@�烧��於����w存取�c�n案操作的落差,同�r也提及��做途�剑�接下�淼闹攸c是�@�烧呷绾慰创�真正的 rootfs。如同前述所及,Linux kernel 2.4 中,initrd 可被��槠鹗��� "root=" 的先前�理�C制,透�^一系列的程序,�f助 kernel 找到最�K的 rootfs,�K一�e�燧d�M系�y,不�^,�^去的�O�其��做了一��假�O:「真正的 rootfs 所在的�b置是 block device,同�r initrd �^非是真正的 rootfs」,�@也是�楹我�� kernel 在第一次��淝腥� user-space �r,是�绦� /linuxrc,而非 /init 或 /sbin/init,因�獒嵴叩� PID �a�� 1 且不可被 kill (�K止),但前者因�橹皇沁^度的存在,�S�r仍可被 kill。
而在 Linux 2.6 引入 initramfs 的�O�後,上述��扭的假�O�c�理方式就不�痛嬖冢�不再�^隔「真正」的 rootfs 是如何「存在」,也就是一�_�C,kernel 就�绦形混� initramfs 中的 /init,作�� PID=1 的 init process,�H以 switch_root 作 rootfs 的重新定位�T了 (�x�裥�)。正因�檫@�拥奶匦裕�核心�_�l者也�� initramfs 的行�榉Q�� [Early User Space],Jeff Garzik 於 2002 年十一月�l表於 lkml 的文章 [initramfs merge, part 1 of N] 提到他的�景:
核心�_�l者很喜�g彼此取笑,�@�e提到的 [Al Viro] 是位知名的 kernel hacker,常常�榱撕葱l核心�O�的一致性�c�S多�_�l者�α�。�@意思就是�f,藉由 Early userspace 整合到核心�O�後,原本很不容易�理的�_�C模式,比方�f LVM (Linux Volume Manager)、�W路�_�C、特�e�Υ嫜b置的�_�C等,都可交由 user-space 的��用程式�iT�理,相��碚f,kernel 就不必�^度涉入,�L�h�碚f,��於�l展的分工、降低系�y�}�s度,以及提高可性�度,均有很大的助益。
基於 initramfs / Early userspace 的想法,核心�_�l者又思考�楹尾�⑦^去�y以有效�S�o但又非得存在不可的程式�a,比方�f do_mount �@一�用以��做�燧d特定�b置或���Υ嬖O�涞墓δ埽�全面�D交�o user-space 的程式去�绦心兀窟@�� kernel 可�P奶�N功能或者效能的改�M。�榇耍�以 H. Peter Anvin �槭椎暮诵拈_�l者引入 [klibc] �c kinit,前者 (至少目�松�) 是最小的 C library ��做,用�碇С轴嵴咚�需 (定位�c [dietlibc] 或 [uclibc] 一�精巧但通用性的 libc ��做不同),而 kinit 就是�⑶笆鲈�本在核心��做的程式 (很�y�慑e且分析的 kernel code) 拉出到 user-space 中,他於 2006 年六月提交的 patch [kinit: replacement for in-kernel do_mount, ipconfig, nfsroot] 就展�F了�⒉煌�的�n案系�y (cramfs, ext2, ext3, jfs, lvm2, minixfs, reiserfs, romfs, xfs, ...) 予以�燧d (即 user-space 的 do_mount)、ipconfig (bootp, dhcp)、nfsmount 等等,整合到 kinit 程式中一�闾�理,kernel image 可因此大幅�s�p。