为什么 initramfs 将根文件系统挂载为只读

为什么 initramfs 将根文件系统挂载为只读

ro根文件系统安装在 initramfs(和 initrd)中的原因是什么?

例如Gentoo initramfs 指南使用以下命令挂载根文件系统:

mount -o ro /dev/sda1 /mnt/root

为什么不是下面的呢?

mount -o rw /dev/sda1 /mnt/root

我可以看到可能有一个很好的理由(并且可能涉及switchroot),但似乎没有在任何地方记录。

答案1

初始虚拟磁盘(initrd) 通常是根文件系统的精简版本,仅包含挂载实际根文件系统并将引导移交给它所需的内容。

initrd 的存在是因为在现代系统中,引导加载程序无法足够智能来可靠地找到根文件系统。对于像引导加载程序这样的小程序来说,有太多的可能性无法涵盖。考虑 NFS 根、非标准 RAID 卡等。引导加载程序必须仅使用 BIOS 以及可以塞入引导扇区的任何代码来完成其工作。

initrd 存储在引导加载程序的某个位置找到,而且它足够小,所占用的额外空间通常不会打扰任何人。 (在小型嵌入式系统中,通常没有“真正的”根,只有 initrd。)

initrd 很宝贵:在任何情况下都必须保留其内容,因为如果 initrd 损坏,系统将无法启动。为了确保这一点,设计者做出的一项设计选择是让引导加载程序以只读方式加载 initrd。还有其他原则也可以实现这一点,例如,在没有“真正”根的小型系统的情况下,您仍然可以挂载单独的/tmp/var/cache等等来存储东西。更改 initrd 的情况很少发生,因此应该非常小心地进行。

回到正常情况一个真正的根文件系统,它最初是只读安装的,因为 initrd 是只读的。然后出于同样的原因,它会尽可能长时间地保持只读状态。根据偏好,任何确实需要完成的对真实根的写入都会推迟到系统启动时,或者至少推迟到启动过程后期当无法满足该偏好时。

在此只读阶段发生的最重要的事情是检查根文件系统以查看它是否已完全卸载。这是引导加载程序当然可以做的事情,而不是将其留给 initrd,但是如果根文件系统不是卸载干净吗?然后它必须打电话fsck来检查并可能修复它。那么,如果它负责这一步而不是等到切换到“真正的”根,那么initrdget会在哪里呢?fsck你可能会说在构建它时需要复制fsck到其中initrd,但现在它更大了。最重要的是,哪个 fsck你会复制吗? Linux 系统经常使用十几个不同的文件系统。您是否只复制initrd创建真正根时所需的根?您是否initrd通过将所有可用程序复制到其中来扩大大小fsck.foo,以防根文件系统稍后迁移到其他文件系统类型,并且有人忘记重建 initrd?

Linux 引导系统架构师明智地选择不让 initrd 承受这些问题的负担。他们将对真实根文件系统的检查委托给真实根文件系统,因为它比 initrd 更适合这样做。

一旦引导过程进行得足够远,可以安全地执行此操作,initrd 就会从真正的根目录下换出:pivot_root(8),并且文件系统以读写模式重新挂载。

答案2

因为在启动期间,根文件系统最初始终以只读方式安装。一旦完成各种自检,它就会将根文件系统重新挂载为读/写,并开始挂载其他文件系统。

答案3

我能想到的一个原因是防止某种腐败。例如,您可以将 ext4 文件系统挂载为 ext2(反之亦然),这在 ro 模式下是安全的,但如果从 initram 挂载 rw 则可能会导致不兼容的格式更改。

哦,还有另一个原因:initramfs 可能没有 fsck,但您可能需要在将其挂载到 rw 之前检查文件系统。

相关内容