Initramfs的概念

简介

对大多数用户来说,是不需要关心initramfs系统的。这些用户使用简单的分区模式没有特殊驱动或配置(比如加密文件系统),因此Linux内核完全有能力转移控制权给系init二进制文件。但是对许多系统,使用initrams是强制要求的。 理解initramfs基本概念(或者为什么需要initramfs)需要理解Linux的引导过程,即使在一个较高的层面上。

Linux启动过程

一旦Linux控制了系统(它是由引导程序加载后得到的),它准备了内存结构和驱动。它转交控制权到一个应用程序(通常是init)它的任务是进一步准备系统并确保在引导结束时所有必须的服务启动运行,并且用户能够登录。init应用通过在其它服务中启动udev守护进程根据探测到的设备进一步加载和准备系统。当udev启动后,所有剩余的没有挂载的文件系统被挂载,并且剩余的服务也都已经启动。

对于所有必要文件和工具驻留同一文件系统的系统,init应用可以完美控制进一步的引导过程。 但是当定义了多个文件系统(或者使用了一些特殊配置),这可能会成为一个棘手的问题:

  • /usr 分区在一个单独的文件系统上时,无法使用存储在 /usr 中的工具和驱动,除非 /usr 可用。如果需要使用这些来让 /usr 可用,那么我们无法启动这个系统。

  • 如果根文件系统是加密的那么Linux内核将无法发现init应用,从而导致系统无法启动。

这个问题的解决方案长期以来一直使用 initrd (初始化根设备)。

initial root disk

initrd 是一个内存中的磁盘结构( ramdisk )它包含文件系统的工具和脚本,用于在控制权被交给根文件系统上的 init 程序前,挂载需要的文件系统。Linux内核调用这个根磁盘上的配置脚本(通常为 linuxrc 但名字不是强制要求),它准备系统,切换真正的根文件系统并调用 init

虽然如此需要 initrd 方法,但是它有几个缺点:

  • 他是一个完整的块设备,需要一个文件系统的开销。它有一个固定的大小。选择一个小的initrd对需要的脚本不合适,让它太大又浪费内存。

  • 因为它是一个真实的静态设备,它在Linux内核中消耗高速缓存并且容易内存和文件管理方法,这使得initrd消耗更多的内存。

initial ram files system

initramfs 是一个基于tmpfs初始内存文件系统(一个固定大小的,内存轻量级文件系统),它也没有使用单独的块设备(所以没有缓存,因此没有前面提到的所有开销)。就像initrd一样,它包含在真正的根文件系统上的init二进制文件被调用之前挂载文件系统需要的工具和脚本。这些工具可以解密抽象层(对加密的文件系统),进行逻辑卷管理,软件磁盘阵列,基于蓝牙驱动程序的文件系统加载器,等等。

initramfs的内容使用cpio归档制作。 cpio 是一个老文件归档解决方案(其生成的归档称为cpio文件)。cpio绝对可以和tar归档相媲美。这里选用cpio是因为其易于实现(代码明了)并且支持tar文件当时不支持的设备文件。

所有的文件,工具,类库,配置(如果可以)等,都放入cpio归档中。这个归档使用gzip进行压缩并存储到Linux内核中。引导加载程序将在引导时将其提供给Linux内核,因此内核知道需要一个initramfs。

一旦检测到,Linux内核将创建一个tmpfs文件系统,取出其中的归档文件,然后启动位于tmpfs文件系统根目录下的init脚本。这个脚本将挂载真实的根文件系统(在确保可以被挂载之后,例如通过一个附加模块,准备一个加密抽象层,等。)以及其他至关重要的文件系统(比如/usr和/var)。

一旦根文件系统和其他重要的文件系统挂载,initramfs中的init脚本将根目录切换到真实的根文件系统最终调用/sbin/init二进制文件继续启动系统。

创建一个initramfs

简介和引导加载程序配置

要创建一个initramfs,知道启动系统需要那些附加驱动,脚本和工具非常重要。例如,如果使用LVM,LVM工具必须在initramfs中。同样,如果使用了软件测盘阵列,就需要 mdadm 工具,等等。

有几种工具可以帮助用户为他们的系统创建initramfs(压缩的cpio归档)。那些想要完全控制的人也可以轻松创建个人自定义initramfs镜像。

一旦创建,bootloader配置将需要调整以通知它将使用initramfs。例如,initramfs存储在/boot/initramfs-3.2.2-gentoo-r5,那么/boot/grub/grub.conf中的配置可能如下所示:

FILE grub.conf Example entry in grub.conf for booting with an initramfs
title Gentoo Linux 3.2.2-r5
root (hd0,0)
kernel /boot/kernel-3.2.2-gentoo-r5
initrd /boot/initramfs-3.2.2-gentoo-r5