Amu*_*umu 56 linux filesystems boot kernel
据我所知,initrd充当块设备,因此需要文件系统驱动程序(如ext2).内核必须至少有一个用于检测文件系统的内置模块initrd.在本文中,介绍了初始RAM磁盘的新模型initramfs,它写成:
但是由于缓存,ramdisks实际上浪费了更多的内存.Linux旨在缓存从块设备读取或写入的所有文件和目录条目,因此Linux将数据复制到ramdisk和从"ramdisk"复制到"页面缓存"(用于文件数据)和"dentry cache"(用于目录条目) .假装是块设备的ramdisk的缺点是它被视为块设备.
什么page cache和dentry cache?在段落中,是否意味着数据被复制,因为ramdisk被视为块设备,因此所有数据都被缓存?
相反,ramfs:
几年前,Linus Torvalds有一个很好的想法:如果Linux的缓存可以像文件系统一样挂载怎么办?只是将文件保存在缓存中,永远不要删除它们,直到它们被删除或系统重新启动?Linus在缓存周围写了一个名为"ramfs"的小包装器,其他内核开发人员创建了一个名为"tmpfs"的改进版本(它可以将数据写入交换空间,并限制给定挂载点的大小,以便在消耗之前填满所有可用的内存).Initramfs是tmpfs的一个实例.
这些基于ram的文件系统会自动增长或缩小以适应它们包含的数据大小.将文件添加到ramfs(或扩展现有文件)会自动分配更多内存,删除或截断文件会释放该内存.块设备和缓存之间没有重复,因为没有块设备.缓存中的副本是数据的唯一副本.最重要的是,这不是新代码,而是现有Linux缓存代码的新应用程序,这意味着它几乎不增加任何大小,非常简单,并且基于经过严格测试的基础架构.
总之,ramfs只是文件打开并加载到内存中,不是吗?
二者initrd并ramfs在编译时拉链,但不同的是,initrd被分解到由在启动内核被安装,而块设备ramfs经由的cpio解压到存储器中.我对么?或者是ramfs一个非常小的文件系统?
最后,直到今天,initrd图像仍然显示在最新的内核中.然而,这initrd实际上是ramfs今天使用的,这个名字只是出于历史目的吗?
rod*_*igo 59
我认为你是对的.
如果您按照启动时所需的步骤操作,则很容易看出差异:
initrdramdev块设备被创建.它是一个基于ram的块设备,它是一个使用内存而不是物理磁盘的模拟硬盘.initrd文件被读取并解压缩到设备中,就像您做的zcat initrd | dd of=/dev/ram0或类似的东西一样.initrd包含一个文件系统的映像,所以现在你可以像往常一样挂载文件系统:mount /dev/ram0 /root.当然,文件系统需要驱动程序,因此如果使用ext2,则必须在内核中编译ext2驱动程序.initramfstmpfs安装:mount -t tmpfs nodev /root.tmpfs不需要驱动程序,它总是在内核上.无需设备,无需其他驱动程序.initramfs直接解压缩到这个新的文件系统:zcat initramfs | cpio -i,或类似的.是的,它仍然initrd在许多地方被调用,虽然它是一个initramfs,特别是在启动加载器中,因为它们只是一个BLOB.操作系统启动时会产生差异.
Jan*_*dec 47
Linux中的文件系统子系统有三层.VFS(虚拟文件系统),它实现系统调用接口并处理交叉挂载点以及默认权限和限制检查.下面是各个文件系统的驱动程序,而这些驱动程序又与块设备的驱动程序接口(磁盘,存储卡等;网络接口是例外).
VFS和文件系统之间的接口是几个类(它是普通的C,所以结构包含指向函数等的指针,但它在概念上是面向对象的接口).主要的三个类是inode描述文件系统中的任何对象(文件或目录)dentry,它描述了目录中的条目file,并描述了进程打开的文件.安装时,文件系统驱动程序创建inode并dentry为其创建根,并且当进程想要访问文件并最终到期时,按需创建其他文件系统驱动程序.这是一个dentry和inode缓存.
是的,它意味着对于每个打开的文件,并到根目录下的任何必须有inode和dentry结构分配的内核内存代表它.
在Linux中,包含用户态数据的每个内存页面都由统一page结构表示.这可能会将页面标记为匿名(可能交换空间,如果可用)或将其与inode某些文件系统关联(可能会写回并从文件系统重新读取),它可以是任意数量的内存映射的一部分,即在某些过程的地址空间中可见.当前在内存中加载的所有页面的总和是页面缓存.
这些页面用于实现mmap接口,而常规的读写系统调用可以通过其他方式由文件系统实现,大多数接口使用也使用页面的泛型函数.有一些通用函数,当请求文件读取时,分配页面并调用文件系统逐个填充它们.对于基于块设备的文件系统,它只计算适当的地址并将此填充委托给块设备驱动程序.
Ramdev是常规的拦截装置.这允许在其上层叠任何文件系统,但它受块设备接口的限制.而这只是填写调用者分配的页面并将其写回的方法.这正是真正的块设备所需要的,例如磁盘,存储卡,USB大容量存储等,但对于ramdisk来说,这意味着数据存在于内存中两次,一次存储在ramdev的内存中,一次存储在由ramdev分配的内存中.呼叫者.
这是旧的实施方式initrd.从initrd罕见和充满异国情调的时候开始.
Tmpfs是不同的.这是一个虚拟文件系统.它为VFS提供的方法是使其工作的绝对最低限度(因此它是inode,dentry和file方法应该做的优秀文档).只有在创建文件时创建并且永不过期的inode缓存中存在相应的inode和dentry时,文件才存在,除非删除该文件.在写入数据时页面与文件相关联,否则表现为匿名页面(数据可以存储为交换,page只要文件存在,结构仍然在使用中).
这意味着内存中没有额外的数据副本,整个过程更加简单,并且由于速度稍快.它只是使用数据结构,作为任何其他文件系统的缓存,因为它是主存储.
这是实现的新方法initrd(initramfs但仍然只调用图像initrd).
它也是实现"posix共享内存"的方式(它只是意味着安装了tmpfs /dev/shm,应用程序可以自由地在那里创建文件并对它们进行映射;简单而有效),最近甚至/tmp和/run(或/var/run)经常安装tmpfs特别是在笔记本电脑上在SSD的情况下,防止磁盘旋转或避免磨损.
Cir*_*四事件 11
最小可运行 QEMU 示例和新手解释
在这个答案中,我将:
希望这些将作为验证和理解差异的更多内部细节的基础。
安装程序会在运行时打印出 QEMU 命令,正如该存储库中所解释的,我们可以轻松生成以下三种工作类型的启动:
根文件系统位于 ext2“硬盘”中:
qemu-system-x86_64 -kernel normal/bzImage -drive file=rootfs.ext2
Run Code Online (Sandbox Code Playgroud)根文件系统位于 initrd 中:
qemu-system-x86_64 -kernel normal/bzImage -initrd rootfs.cpio
Run Code Online (Sandbox Code Playgroud)
-drive没有给出。
rootfs.cpio包含与 相同的文件rootfs.ext2,只不过它们是CPIO格式,这与 类似.tar:它序列化目录而不压缩它们。
根文件系统位于 initramfs 中:
qemu-system-x86_64 -kernel with_initramfs/bzImage
Run Code Online (Sandbox Code Playgroud)
既没有-drive也没有-initrd给出。
with_initramfs/bzImage是一个使用与 相同的选项编译的内核normal/bzImage,除了一个:CONFIG_INITRAMFS_SOURCE=rootfs.cpio指向与示例中完全相同的 CPIO -initrd。
通过比较这些设置,我们可以得出每个设置最基本的属性:
在硬盘设置中,QEMU 将 bzImage 加载到内存中。
这项工作通常由引导加载程序/固件在真实硬件(例如 GRUB)中完成。
Linux 内核启动,然后使用其驱动程序从磁盘读取根文件系统。
在 initrd 设置中,除了将内核加载到内存中之外,QEMU 还执行一些进一步的引导加载程序工作:它还:
rootfs.cpio内存中这一次,内核直接使用rootfs.cpio内存中的数据,因为不存在硬盘。
写入在重新启动后不会持久,因为所有内容都在内存中
在 initramfs 设置中,我们构建内核的方式略有不同:我们还将 赋予rootfs.cpio内核构建系统。
然后,内核构建系统知道如何将内核映像和 CPIO 粘贴到单个映像中。
因此,我们需要做的就是将 bzImage 传递给 QEMU。QEMU 将其加载到映像中,就像对其他设置所做的那样,但不需要其他任何东西:CPIO 也会加载到内存中,因为它粘附到内核映像!
添加上面优秀答案中未提及的initrd另一个值得注意的区别。initramfs
initrd默认移交给用户pid 1空间/sbin/initpid 1在/init因为它可能成为一个陷阱(参见https://unix.stackexchange.com/a/147688/24394)
| 归档时间: |
|
| 查看次数: |
37525 次 |
| 最近记录: |