![为什么 Linux 在启动时使用初始 RAM 磁盘?](https://linux22.com/image/61681/%E4%B8%BA%E4%BB%80%E4%B9%88%20Linux%20%E5%9C%A8%E5%90%AF%E5%8A%A8%E6%97%B6%E4%BD%BF%E7%94%A8%E5%88%9D%E5%A7%8B%20RAM%20%E7%A3%81%E7%9B%98%EF%BC%9F.png)
我想知道 :
initrd
在引导过程的第一部分使用 an 然后用于pivot_root
将 root 放在真实磁盘上的目标是什么?为什么不只使用磁盘上的内容呢?
答案1
为什么不只使用磁盘上的内容呢?
你可以。您不必使用 initrd(或 initramfs,自内核 2.6.13 以来更新且更广泛的版本)。
使用它们的原因是发行版内核是通用的,并且必须支持各种开箱即用的硬件。对于安装根文件系统至关重要的不同硬件的一些驱动程序可能是互斥的(我不确定),但无论如何,构建所有可能性 - 这是你必须做的 - 将使对于一个非常大的内核。
因此,驱动程序不是内置在内核中,而是位于单独的二进制模块中。这是 initramdfs/initrd 的主要有效负载;它允许内核加载适当的硬件驱动程序,以便可以正确安装根文件系统。
答案2
在出现 initrd 之前,您必须在内核命令行上传递要用作根文件系统的分区的设备名称。内核有特殊的一次性代码来解析这个名称并识别一些常见的字符串,并将它们转换为众所周知的dev_t
数字。也就是说,内核在内部将设备简单地理解为数组中的数字索引,并且要安装一个设备,您必须知道它的编号。
在即插即用和热插拔出现之前,当系统只有一两个始终存在的磁盘时,这种方法可以正常工作。如果您的根文件系统是,/dev/hda1
那么它总是如此。然而,即插即用的出现却让这个问题变得不那么重要。如今,您可能有十几个内部磁盘驱动器,或者 USB、ISCSI 或其他什么,为了缩短启动时间,它们会被并行探测,因此它们的设备名称可能会根据哪个首先响应而改变这意味着您的内核命令行指定的设备名称很容易变得不正确,并且您无法启动。
为了解决这个问题,引入了 UUID。通过UUID指定设备,无论是sda还是sde,总能找到正确的驱动器。然而,这确实需要实际查看驱动器,并且比简单的静态名称 ->dev_t
映射内核启动代码可以做到的要复杂得多。我们决定内核不适合如此复杂的情况,因此 initrd 诞生了。它可以具有识别正确的根设备并安装它所需的任何实用程序。它还可以执行任意复杂的操作,例如启动网络并获取 DHCP 租约以访问 nfs 或 iSCSI 根。您需要 initrd 的其他事情包括设置 raid 和 lvm 或加密以进行磁盘访问。
答案3
混乱完美概括了它。我只是添加一个初始虚拟磁盘(或初始化程序) 是选修的。在某些情况下,它是必需的,例如,当/usr
位于单独的文件系统上时,这曾经被宣传为良好实践。
还,系统,在许多 Linux 发行版上都可以找到,需要/usr
在启动时可用。否则你必须提供一个初始化程序/usr
在切换到真正的根之前准备好正确安装的根文件系统。
拥有漂亮的启动画面还需要初始化程序。所有现代的主要发行版都提供引导启动屏幕,而不是引导时臭名昭著的日志消息流。
答案4
initrd 的任务是使真正的根设备可用并切换到其中。真正的根设备可以是(例如)硬盘驱动器上的分区、网络中的 nfs 共享、USB 记忆棒上的文件系统、伪文件系统或其他东西。
几乎每个 initrd 都有一个名为 的例程mountroot
。这是搜索正确的根文件系统并将其安装的函数(通常安装到/root
initrd 本身中(不要将其与 root 的主目录混淆))。
引导管理器必须指向磁盘(或任何地方)内核和 initrd 所在的正确位置。内核被执行,initrd 被直接解压到系统 RAM 中。/
initrd中通常有一个名为 的脚本init
。这就是挂载伪文件系统(sysfs、procfs、dev...)的部分。还有一些可以访问的环境变量(通过/proc/cmdline
),例如debug
, break
, ...
挂载根文件系统后,脚本将进行清理并切换到新的根。然后该进程将/sbin/init
取代 pid 号 1,即之前的 init-scripts pid。从那时起,有不同的机制来完成引导过程的其余部分(upstart、SysVinit、systemd)。