在这篇介绍中初始化文件系统Robert Landley 提到以下内容作为 ramfs 背后的动机。
但虚拟磁盘实际上由于缓存而浪费了更多的内存。 Linux 被设计为缓存从块设备读取或写入块设备的所有文件和目录条目,因此 Linux 将数据往返于 ramdisk 复制到“页面缓存”(用于文件数据)和“目录项缓存”(用于目录条目) 。虚拟磁盘伪装成块设备的缺点是它被当作块设备对待。
几年前,Linus Torvalds 有一个绝妙的想法:如果 Linux 的缓存可以像文件系统一样挂载会怎样?只是将文件保留在缓存中,并且在删除它们或系统重新启动之前永远不要删除它们? Linus 在缓存周围编写了一个名为“ramfs”的小型包装器,其他内核开发人员创建了一个名为“tmpfs”的改进版本(它可以将数据写入交换空间,并限制给定安装点的大小,以便在使用之前将其填满)所有可用内存)。 Initramfs 是 tmpfs 的一个实例。
这让我相信 ramfs(以及 initramfs)是一种将内部缓存结构公开为文件系统的机制 - 使用 initramfs 驱动程序。
但是缓存本身的存在不是依赖于缓存的块设备的存在吗从?这意味着即使要创建一个纯粹基于 RAM 的文件系统,我们也需要从ramfs
缓存中创建(或模拟)一个块设备 - 这看起来像是 initrd 最初引入的问题。我确信我在这里遗漏了一些东西,但我不确定是什么。
传递给内核的 cpio 存档也可以驻留在块设备(通常是硬盘)上,因此为了挂载 initramfs 内容,内核是否仍然需要文件系统驱动程序?
答案1
对于ramsfs/initrams来说,缓存fs的设备是“空”的。如果您查看以下描述/Documentation/filesystems/ramfs-rootfs-initramfs.txt
:
通常,所有文件都被 Linux 缓存在内存中。从后备存储(通常是安装文件系统的块设备)读取的数据页会保留下来,以备再次需要时使用,但会标记为干净(可释放),以防虚拟内存系统需要该内存用于其他用途。同样,写入文件的数据一旦写入后备存储,就会被标记为干净,但会出于缓存目的而保留,直到虚拟机重新分配内存。类似的机制(目录项缓存)极大地加快了对目录的访问速度。
对于 ramfs,没有后备存储。写入 ramfs 的文件照常分配目录项和页面缓存,但没有地方可以写入它们。这意味着这些页面永远不会被标记为干净,因此当虚拟机寻求回收内存时无法释放它们。
因此,“将内部缓存结构公开为文件系统的机制”并没有错,但不是我所描述的——它是一个使用通常的内部缓存结构的文件系统,但没有地方“备份它”(如内存盘有),所以它仅有的存在于缓存中,并且从不使用使页面无效和写回页面的机制。
至于cpio
文件,再看一下ramfs-rootfs-initramfs.txt
:
旧的 initrd 始终是一个单独的文件,而 initramfs 存档链接到 Linux 内核映像中。 (目录 linux-*/usr 专门用于在构建过程中生成此存档。)
因此,cpio
使用与加载内核相同的方法来加载,可以从块设备,或者通过网络,或者通过鸽子载体,或者其他方式。没关系。引导加载程序会处理这个问题,内核不需要文件系统驱动程序。
答案2
ramfs 的要点在于它摆脱了块设备。文件系统的内容是通过文件系统接口填充的,并且由于没有支持块设备,因此数据保留在缓存中。在旧的方式中,后备存储充当写入文件系统映像的块设备。然后将其安装为文件系统。这种方法(RAM被缓存在RAM中)的问题得到了解决,不是通过移除缓存,而是移除块设备。
是的,cpio
存档通常来自块设备,但不一定。它可以来自网络、原始块设备等。cpio 存档也可以选择成为内核映像的一部分。当然,引导加载程序必须有一种机制将内核和 initramfs 加载到 RAM 中,但这是引导加载程序的问题,而不是内核的问题。 initramfs 的要点在于,最终的系统可以非常多样化,有十几个不同的文件系统可供选择,不同的较低级别磁盘驱动器接口等。通过使用 initramfs,可以将内核配置为更通用,无需编译一百万个驱动程序,而是可以作为模块提供。事实上,内核中不需要任何文件系统驱动程序,它们都可以作为模块按需加载。