Contents

Initrd和initramfs有什么区别?

1. 概述

在 Linux 中,initrd (初始 RAM 磁盘)和*initramfs *(初始 RAM 文件系统)命令是我们可以用来将临时根文件系统加载到 RAM 或系统内存以成功启动的不同方法

我们需要一个initrdinitramfs文件系统来将内核加载到内存中,并将根文件系统从内存中挂载到硬盘上。

我们可以使用initrdinitramfs来做准备,例如在挂载真正的根文件系统(在系统硬盘或存储上)之前启动内核和设置硬件设备。

在本教程中,我们将仔细研究*initrd initramfs *。此外,我们将探讨它们的一些差异和它们共有的相似之处

2. 什么是initrd

** initrd使我们能够通过引导加载程序加载 RAM 磁盘。加载的 RAM 磁盘作为根文件系统挂载,并从中运行不同的程序。**我们还可以从不同的设备挂载一个新的根文件系统,使引导加载程序将以前的initrd根目录移动到不同的目录,然后我们可以卸载它。

initrd的主要设计是让我们的系统启动发生在前面的两个阶段:

  • 内核分配最小的编译驱动程序集
  • 从initrd加载附加模块

initrd通常用作块设备,将其编译到内核中需要文件系统驱动程序,例如ext2ext3ext4

内核要成功检测*initrd 的文件系统,*它必须至少有一个可用的内置模块。

因为initrd磁盘的大小是固定的,所以在initrd映像上读取和写入的所有常见操作都被低效地缓冲到我们系统的主内存中。

注意:initrd已被弃用并被initramfs 取代。

2.1. 使用initrd 的引导过程

下面我们来看看更详细的initrd引导过程说明:

  • 引导加载程序加载内核和初始 RAM 磁盘。
  • 内核将initrd转换为 RAM 磁盘。此外,它还会清除initrd 正在使用的内存。
  • 内核在/dev/ram0文件路径中搜索根设备,如果没有找到,内核将执行change_root过程。
  • 如果在*/dev/ram0*目录中找到,则将其挂载为根文件系统。
  • Init 加载实际文件系统并使用pivot_root系统调用将根文件系统移动到目录。
  • Init在新创建的根文件系统上执行*/sbin/init* ,执行通常的引导顺序。
  • 引导加载程序断开initrd文件系统。

**注意:更改我们的根目录不一定涉及卸载它。这使我们可以在整个过程中让进程在initrd上运行。**此外,我们可以轻松访问挂载在initrd 下的文件系统。

2.2. 如何访问initrd

让我们创建一个新目录并从*/boot/复制initrd.img*文件:

$ mkdir initrd_test
$ cd initrd_test
$ cp /boot/initrd.img .
$ ls
initrd.img

像 Debian 这样的一些系统要求我们首先提取initrd文件。让我们重命名文件以具有*.gz*扩展名,以便我们可以提取它。此外,让我们使用file 来确保解压后的文件实际上是 CPID 格式:

$ mv initrd.img initrd.img.gz
$ gunzip initrd.img.gz
$ file initrd.img
initrd.img: ASCII cpio archive (SVR4 with no CRC)

让我们使用cpio 命令来提取图像:

$ cpio -id < initrd.img
62 blocks
$ ls
 initrd.img kernel

我们在 Linux Ubuntu 操作系统上提取了*initrd.img文件的内容。*我们提取后获得的文件数量可能会因我们的 Linux 发行版而异。

3. 什么是initramfs

** initramfs是加载到内存中的初始文件系统的cpio归档文件。**此加载发生在内核完成启动系统之后,并且在用户空间开始init过程之前。

**在加载主根之前,内核会将 initramfs的内容作为初始根文件系统加载。**初始根目录包含挂载“真实”根文件系统和初始化系统所需的文件。这些文件主要包含内核模块。

Linux 内核是兼容和自适应的。这允许它支持动态加载和卸载文件等功能。内核的几个部分可以转换为模块,允许 Linux 系统构建内核,只将基本要素编译到主内核中。此外,为所有其他可能的特性或硬件提供功能作为一个模块,允许我们根据需要加载或卸载它们。

*** initramfs*还允许内核从特殊的 RAM 文件系统访问模块。这使得从磁盘或单独的文件系统访问根文件系统成为可能。**

3.1. initramfs 的工作原理

initramfs 作为压缩的cpio存档提供。

可以使用包含在引导过程早期加载的微码数据的解压缩cpio存档在映像前添加。 在引导期间,内核遵循以下过程:

  • 如果我们在initramfs启动期间存在压缩的cpio存档,它将提取它并将微码数据从中加载到 CPU。
  • 如果在initramfs启动期间存在未压缩的cpio存档,它将跳过存档并将文件的其余部分设置为基本initramfs。相反,它将整个initramfs视为基本initramfs
  • 它将基本的initramfs解压到基于 RAM 的磁盘中,将其视为压缩的(Debian 上的 gzip,Ubuntu 上的 LZ4)cpio存档文件。

从那里,大部分内核初始化和引导代码将被移动到该磁盘并在用户模式下运行。其他类似地从内核移出的进程包括:

  • 启动时网络设置
  • 寻找真正的根盘
  • ACPI 设置
  • 处理initrd样式的 RAM 磁盘

3.2. initramfs的优点

早期引导过程的定制变得更加容易。我们可以使用用户空间代码来实现这一点,这消除了修补内核以更改系统引导方式的要求。

将初始化代码移动到用户空间可以更容易地编写代码。

我们需要用户空间代码通过系统调用来处理内核,从而产生更干净、更安全的代码。

3.3. 如何访问initramfs

initramfs-tools-core 为我们提供了lsinitramfs  ,我们可以使用它来列出initramfs中的文件。

我们还可以使用unmkinitramfsinitramfs中提取文件。

让我们假设path/to/initrd已经作为一个空目录存在并且输出文件*/initrd.img*是一个 ASCII cpio存档(没有 CRC 的 SVR4)。

我们将考虑在initrd映像之前添加微码。让我们提取微码并读取 STDERR 显示:

$ cd path/to/initrd/
$ cpio -i < /initrd.img
62 blocks

我们可以通过以下方式提取基本的initrd

$ cd path/to/initrd/
$ dd if=/initrd.img of=initrd.img bs =512 skip=62
$ zcat initrd.img | cpio -i 

注意:我们应该调整跳过值以匹配cpio STDERR 输出。

让我们检查一下微码cpio存档大小:

$ cpio -t </initrd.img >/dev/null

4. initrdinitramfs 的区别

我们可以将initrd用于 Linux 内核 2.4 及更低版本。相反,initramfs适用于内核 2.6 及更高版本。

initrd编译到内核中至少需要一个文件系统驱动程序,这增加了启动时的灵活性、简单性和内存效率。

使用initramfs,我们可以创建一个包含内核将提取到tmpfs 的文件的存档,这使得文件访问非常快。