繁体   English   中英

initrd和initramfs之间的区别?

[英]The difference between initrd and initramfs?

据我所知, initrd充当块设备,因此需要文件系统驱动程序(例如ext2 )。 内核必须至少有一个内置模块来检测initrd文件系统。 在本文中, 介绍了初始RAM磁盘的新模型initramfs ,它写成:

但是由于缓存,ramdisks实际上浪费了更多的内存。 Linux旨在缓存从块设备读取或写入的所有文件和目录条目,因此Linux将数据复制到ramdisk和从“ramdisk”复制到“页面缓存”(用于文件数据)和“dentry cache”(用于目录条目) 。 假装是块设备的ramdisk的缺点是它被视为块设备。

什么是page cachedentry cache 在段落中,是否意味着数据被复制,因为ramdisk被视为块设备,因此所有数据都被缓存?

相比之下, ramfs

几年前,Linus Torvalds有一个很好的想法:如果Linux的缓存可以像文件系统一样挂载怎么办? 只是将文件保存在缓存中,永远不要删除它们,直到它们被删除或系统重新启动? Linus在缓存周围写了一个名为“ramfs”的小包装器,其他内核开发人员创建了一个名为“tmpfs”的改进版本(它可以将数据写入交换空间,并限制给定安装点的大小,以便在消耗之前填满所有可用的内存)。 Initramfs是tmpfs的一个实例。

这些基于ram的文件系统会自动增长或缩小以适应它们包含的数据大小。 将文件添加到ramfs(或扩展现有文件)会自动分配更多内存,删除或截断文件会释放该内存。 块设备和缓存之间没有重复,因为没有块设备。 缓存中的副本是数据的唯一副本。 最重要的是,这不是新代码,而是现有Linux缓存代码的新应用程序,这意味着它几乎没有增加任何大小,非常简单,并且基于经过严格测试的基础架构。

总之, ramfs只是文件打开并加载到内存中,不是吗?

initrdramfs都是在编译时压缩的,但不同的是, initrd是一个解压缩的块设备,由内核在启动时挂载,而ramfs通过cpio解压缩到内存中。 我对么? 或者ramfs是一个非常小的文件系统?

最后,直到今天, initrd映像仍然存在于最新的内核中。 但是, initrd实际上是今天使用的ramfs ,这个名字只是出于历史目的吗?

我认为你是对的。

如果您按照启动时所需的步骤操作,则很容易看出差异:

initrd

  • 创建ramdev块设备。 它是一个基于ram的块设备,它是一个使用内存而不是物理磁盘的模拟硬盘。
  • 读取initrd文件并将其解压缩到设备中,就好像您执行了zcat initrd | dd of=/dev/ram0 zcat initrd | dd of=/dev/ram0或类似的东西。
  • initrd包含文件系统的映像,所以现在你可以像往常一样mount /dev/ram0 /root文件系统: mount /dev/ram0 /root 当然,文件系统需要驱动程序,因此如果使用ext2,则必须在内核中编译ext2驱动程序。
  • 完成!

initramfs

  • 安装了tmpfsmount -t tmpfs nodev /root tmpfs不需要驱动程序,它总是在内核上。 无需设备,无需其他驱动程序。
  • initramfs直接解压缩到这个新的文件系统中: zcat initramfs | cpio -i zcat initramfs | cpio -i或类似的。
  • 完成!

是的,尽管它是一个initramfs ,它仍然在很多地方被称为initrd ,特别是在引导加载器中,因为它们只是一个BLOB。 操作系统启动时会产生差异。

Dentry(和inode)缓存

Linux中的文件系统子系统有三层。 VFS(虚拟文件系统),它实现系统调用接口并处理交叉挂载点以及默认权限和限制检查。 下面是各个文件系统的驱动程序,而这些驱动程序又与块设备的驱动程序接口(磁盘,存储卡等;网络接口是例外)。

VFS和文件系统之间的接口是几个类(它是普通的C,所以结构包含指向函数等的指针,但它在概念上是面向对象的接口)。 主要的三个类是inode ,它描述文件系统中的任何对象(文件或目录) dentry ,它描述了目录和file中的条目,该file描述了进程打开的文件。 安装时,文件系统驱动程序为其根创建inodedentry ,并在进程想要访问文件并最终到期时按需创建其他文件系统驱动程序。 这是一个dentry和inode缓存。

是的,它确实意味着对于每个打开的文件和根目录下的任何目录,都必须在内核内存中分配inodedentry结构来表示它。

页面缓存

在Linux中,包含用户态数据的每个内存页面由统一page结构表示。 这可能会将页面标记为匿名(如果可用,可能会交换到交换空间),或者将其与某些文件系统上的inode关联(可能会被写回并从文件系统重新读取),并且它可以是任意数量内存的一部分地图,即在某个过程的地址空间中可见。 当前在内存中加载的所有页面的总和是页面缓存。

这些页面用于实现mmap接口,而常规的读写系统调用可以通过其他方式由文件系统实现,大多数接口使用也使用页面的泛型函数。 有一些通用函数,当请求文件读取时,分配页面并调用文件系统逐个填充它们。 对于基于块设备的文件系统,它只计算适当的地址并将此填充委托给块设备驱动程序。

ramdev(ramdisk)

Ramdev是常规的拦截装置。 这允许在其上层叠任何文件系统,但它受块设备接口的限制。 而这只是填写调用者分配的页面并将其写回的方法。 这正是真正的块设备所需要的,例如磁盘,存储卡,USB大容量存储等,但对于ramdisk而言,这意味着数据存在于内存中两次,一次存储在ramdev的内存中,一次存储在由ramdev分配的内存中。呼叫者。

这是实现initrd的旧方法。 从initrd罕见和充满异国情调的时候开始。

TMPFS

Tmpfs是不同的。 这是一个虚拟文件系统。 它为VFS提供的方法是使其工作的绝对最低限度(因此它是inode,dentry和file方法应该做的优秀文档)。 只有在创建文件时创建并且永不过期的inode缓存中存在相应的inode和dentry时,文件才存在,除非删除该文件。 页面在写入数据时与文件相关联,否则表现为匿名page (数据可以存储为交换,只要文件存在, page结构仍然在使用)。

这意味着内存中没有额外的数据副本,整个过程更简单,并且由于速度稍快。 它只是使用数据结构,作为任何其他文件系统的缓存,因为它是主存储。

这是实现initrd的新方法( initramfs ,但图像仍然只调用initrd )。

它也是实现“posix共享内存”的方式(这意味着tmpfs安装在/dev/shm ,应用程序可以自由地在那里创建文件并对其进行mmap;简单而有效),最近甚至是/tmp/run (或者/var/run )通常特别在笔记本电脑上安装了tmpfs,以防止磁盘旋转或在SSD情况下避免磨损。

在上面的优秀答案中没有提到的initrdinitramfs之间添加另一个值得注意的区别。

  • 使用initrd ,内核默认移交给/sbin/init用户空间pid 1
  • 然而,较新的initramfs会更改并在/init执行pid 1

因为它可能成为一个陷阱(见https://unix.stackexchange.com/a/147688/24394

最小的可运行QEMU示例和新手解释

在这个答案中,我将:

  • 提供最小的可运行的Buildroot + QEMU示例供您测试
  • 解释两者之间最基本的区别,对于那些可能在Google上搜索的人来说

希望这些将作为验证和理解更多内部细节差异细节的基础。

最小化设置在这里完全自动化 ,这是相应的入门

安装程序在运行时打印出QEMU命令,并且如该回购中所述,我们可以轻松生成以下三种工作类型的启动:

  1. 根文件系统在ext2“硬盘”中:

     qemu-system-x86_64 -kernel normal/bzImage -drive file=rootfs.ext2 
  2. 根文件系统在initrd中:

     qemu-system-x86_64 -kernel normal/bzImage -initrd rootfs.cpio 

    没有给出-drive器。

    rootfs.cpio包含相同的文件作为rootfs.ext2 ,除了他们是在CPIO格式,这是类似.tar :它系列化目录,而对其进行压缩。

  3. 根文件系统在initramfs中:

     qemu-system-x86_64 -kernel with_initramfs/bzImage 

    既没有-drive也没有-initrd

    with_initramfs/bzImage是一个使用与normal/bzImage相同的选项编译的内核,除了一个: CONFIG_INITRAMFS_SOURCE=rootfs.cpio指向与-initrd示例完全相同的CPIO。

通过比较设置,我们可以得出每个设置的最基本属性:

  1. 在硬盘设置中,QEMU将bzImage加载到内存中。

    这项工作通常由引导程序/固件在真实硬件(如GRUB)中完成

    Linux内核启动,然后使用其驱动程序从磁盘读取根文件系统。

  2. 在initrd设置中,除了将内核加载到内存中之外,QEMU还会执行一些其他的引导程序工作:它还:

    这一次,内核直接使用内存中的rootfs.cpio ,因为没有硬盘。

    由于一切都在内存中,因此写入在重新启动时不会持久

  3. 在initramfs设置中,我们构建内核有点不同:我们还将rootfs.cpio给内核构建系统。

    然后,内核构建系统知道如何将内核映像和CPIO一起粘贴到单个映像中。

    因此,我们需要做的就是将bzImage传递给QEMU。 QEMU将其加载到图像中,就像它对其他设置一样,但不需要其他任何东西:CPIO也会被加载到内存中,因为它粘在内核映像上!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM