返回

Linux 启动过程:initrd 和 initramfs 有什么区别?

Linux

Linux 启动过程探秘:initrd 与 initramfs 的前世今生

在 Linux 系统启动的浩瀚流程中,initrdinitramfs 如同两位幕后英雄,默默地为操作系统的加载和运行搭建着桥梁。它们的名字相似,功能也有一定的重叠,但它们的历史背景、实现方式以及在现代 Linux 系统中的角色都有着显著的差异。本文将深入探讨 initrdinitramfs 的区别,揭开它们神秘的面纱。

从古老的 initrd 说起:模拟块设备的权宜之计

早期的 Linux 系统启动面临着一个难题:根文件系统通常位于独立的分区或设备上,而系统启动初期,内核尚未加载驱动程序,无法访问这些设备。这就像一辆汽车缺少了启动马达,空有强劲的引擎却无法发动。

为了解决这个问题, initrd (initial ramdisk) 应运而生。它本质上是一个镜像文件,包含了启动过程中必需的驱动程序和启动脚本。在系统启动初期, initrd 被加载到内存中并模拟成一个块设备。内核可以像访问普通硬盘一样访问 initrd ,从中加载驱动程序,最终成功挂载真正的根文件系统。

让我们看一个简单的例子,假设你的根文件系统位于 SCSI 硬盘上,但你的 Linux 内核并没有编译进 SCSI 驱动。这时,你可以创建一个 initrd 镜像,将 SCSI 驱动打包进去。系统启动时,会先加载 initrd ,并从中加载 SCSI 驱动,之后才能访问 SCSI 硬盘并挂载根文件系统。

然而,将 initrd 模拟成块设备也带来了一些弊端。由于 Linux 内核会对块设备进行缓存操作, initrd 中的数据会被复制到页缓存 (page cache) 和目录项缓存 (dentry cache) 中。这就意味着数据被存储了两份,白白浪费了宝贵的内存资源。

ramfstmpfs 的诞生:化繁为简,拥抱内存文件系统

为了克服 initrd 的缺陷,Linux 开发者们另辟蹊径,创造了 ramfstmpfs 这两种内存文件系统。

ramfs 的思想非常简单:既然内核本身就拥有缓存机制,为什么不直接将文件系统构建在缓存之上呢? ramfs 将文件数据直接存储在页缓存中,省去了模拟块设备的繁琐步骤,也避免了数据冗余的问题。你可以将 ramfs 想象成一个完全运行在内存中的磁盘,它非常快速,但存储在其中的数据会随着系统重启而消失。

tmpfs 则是在 ramfs 基础上的进一步发展。它不仅可以利用内存作为存储空间,还可以使用交换分区来存储数据,并且可以限制单个挂载点的最大容量,防止内存被过度占用。tmpfs 通常被用于存储临时文件,例如进程的 PID 文件、共享内存段等。

initramfs :站在巨人肩膀上的集大成者

initramfs (initial ram filesystem) 正是基于 tmpfs 实现的。它继承了 tmpfs 的所有优点,同时针对系统启动过程进行了优化。

initrd 需要先解压再挂载不同, initramfs 在编译阶段就被打包成 cpio 格式,内核可以直接将其解压到内存中,并以 tmpfs 的方式挂载。这种方式更加高效简洁,也更节省内存空间。

现代 Linux 系统中的 initrdinitramfs

尽管 initramfs 在效率和灵活性方面都优于 initrd ,但在一些 Linux 发行版中,你仍然可以看到 initrd 的身影。这是因为 initrd 已经成为了一种历史遗留,为了保持向后兼容性,一些发行版仍然保留了对 initrd 的支持。

实际上,在这些发行版中, initrd 通常只是一个指向 initramfs 的符号链接。也就是说,你所看到的 initrd 实际上已经是现代化的 initramfs 了。

常见问题解答

  1. initrdinitramfs 的主要区别是什么?

    initrd 模拟成一个块设备,而 initramfs 直接使用内存文件系统。 initramfsinitrd 更加高效和灵活,并且更加节省内存。

  2. 为什么一些 Linux 发行版仍然使用 initrd 这个名字?

    为了保持向后兼容性。在这些发行版中, initrd 通常只是一个指向 initramfs 的符号链接。

  3. initramfs 是如何创建的?

    initramfs 通常在编译内核时创建。你可以使用 mkinitramfsupdate-initramfs 命令来创建或更新 initramfs 镜像。

  4. initramfs 中包含哪些内容?

    initramfs 中包含了启动过程中必需的驱动程序、启动脚本和其他文件。

  5. 如何调试 initramfs 相关的问题?

    你可以使用内核参数 rdinitdebug 来开启 initramfs 的调试输出。