Linux-initramfs

 

1. 内核启动问题
2. 解决方案
2.1 ramdisk(好比initrd)
2.2 tmpfs(好比initramfs)
2.3 ramdisk vs ramfs
2.4 临时文件系统
2.4.1 观察tmpfs
2.4.2 Initramfs
2.4.3 查看initramfs
2.4.4 建立initramfs
2.5 Linux系统中的initramfs
2.6 cpio归档文件
3. 高级用户
3.1 制做本身的initramfs
3.2 Initramfs编程
3.3 使用更新的工具

1. 内核启动问题

当Linux内核引导系统时,它必须找到并运行第一个用户程序,一般称为“init”。(大多数较新的版本使用systemd做为默认init)
用户程序存在于文件系统中,所以Linux内核必须找到并挂载第一个(或“根”)文件系统才能成功启动。
一般,可用的文件系统列在文件 /etc/fstab 中,经过 mount 程序能够找到它们。可是 /etc/fstab 自己就是一个存储在文件系统中的文件。
找到第一个文件系统是鸡和蛋的问题,为了解决这个问题,内核开发人员建立了内核命令行选项“root =”,以指定根文件系统所在的设备。

二十年前,“root =”很容易解释。它多是软盘驱动器,也多是硬盘驱动器上的分区。(可用硬件设备及文件系统很是少,很容易指定)
如今,根文件系统能够在几十种不一样类型的硬件上,文件系统也有几十种,甚至能够在RAID中分布在其中的几种硬件上。压缩,加密,环回挂载,存在与网络上等等状况。
新的硬件,新的文件系统,新的压缩,加密方法还会愈来愈多。

2. 解决方案

为了不将如此多的特殊状况硬编码到内核中,使用了具备临时根文件系统的初始启动阶段 - 如今称为早期用户空间。此根文件系统能够包含用户空间帮助程序,它们执行硬件检测,模块加载和设备发现,以便安装真正的根文件系统。

2.1 ramdisk(好比initrd)

在2.4及更早版本上,主要使用ramdisk(好比initrd), 基于ram的块设备, 但因为模仿块设备,致使它是固定大小的内存块,须要像磁盘同样进行格式化和安装,(操做工具mke2fs,losetup)。须要文件系统驱动。这形成额外的开销,资源的浪费。固定的大小还不能扩展。

2.2 tmpfs(好比initramfs)

Rootfs是ramfs(或tmpfs,若是已启用)的特殊实例,具体表现好比Initramfs文件。
到2.6版本时期,Linus在缓存周围写了一个名为“ramfs”的小包装器,Ramfs是一个很是简单的文件系统,它将Linux的磁盘缓存机制(页面缓存和dentry缓存)导出为可动态调整大小的基于RAM的文件系统。
ramfs的一个缺点是你能够继续写入数据直到你填满全部内存,而VM没法释放它,由于VM认为文件应该写入后备存储(而不是交换空间),可是ramfs没有任何后备存储。
所以,只容许root(或可信用户)对ramfs mount进行写访问。

其余内核开发人员建立了一个名为“tmpfs”的改进版本.tmpfs(之前称为shmfs)基于启动时使用的ramfs代码,,但与ramfs不一样,它支持交换较少使用的页面以交换空间以及文件系统大小和inode限制以防止内存不足的状况(默认为物理RAM的一半和RAM页面的一半)。
(它能够将数据写入交换空间,并限制给定挂载点的大小,避免填满全部可用的内存)。Initramfs是tmpfs的一个实例。
能够容许普通用户对tmpfs挂载进行写访问。这些基于ram的文件系统会自动增加或缩小以适应它们包含的数据大小。物尽其用,不会浪费额外的空间,不须要模拟块设备操做的额外开销。

2.3 ramdisk vs ramfs

2.4及更早版本使用 2.6以上版本
ramdisk ramfs > tmpfs
initrd initramfs
基于ram的块设备 基于ram的文件系统
固定大小的内存块 会自动增加或缩小以适应包含的数据大小
资源浪费,模拟块设备,额外的开销 物尽其用
旧的initrd始终是一个单独的文件 而initramfs存档连接到linux内核映像
initrd文件是一个gzip压缩的文件系统映像(在例如ext2,须要内置的驱动程序) initramfs存档是一个gzip压缩的cpio存档(好比tar更简单)
内核的cpio提取代码很是小,并且还能够在启动过程当中丢弃__init文本和数据。
旧的initrd(称为/initrd,而不是/init)
运行程序进行一些设置,而后返回到内核
而initramfs的init程序不会返回内核.
若是/init须要切换控制,它可使用新的根设备进行超载/执行另外一个init程序。
当切换另外一个根设备时,initrd将pivot_root,而后卸载ramdisk。 initramfs是rootfs,既不能使用pivot_root rootfs,也没法卸载。
而是删除rootfs中的全部内容以释放空间 (find -xdev / -exec rm '{}' ';'), 
使用新根 (cd /newmount; mount --move . /; chroot .), 覆盖rootfs。
将 stdin/stdout/stderr 附加到新的 /dev/console, 并执行新的init。
小结
ramdisk,模拟块设备,实例是initrd,前文描述的弊端,已不多使用。
tmpfs,临时文件系统,是ramfs的改进版本,实例是目前主流的initramfs,初始ram文件系统。

2.4 临时文件系统

2.4.1 观察tmpfs

tmpfs是许多类Unix操做系统上临时文件存储设施的通用名称。能够经过df观察到
在某些Linux发行版(例如Debian,Ubuntu)上,/tmp是普通目录,但/dev/shm使用tmpfs。
如下是arch linux环境
$ df
Filesystem 1K-blocks Used Available Use% Mounted on
dev 4072256 0 4072256 0% /dev
run 4079692 864 4078828 1% /run
/dev/sdb6 31364968 14256088 15492548 48% /
/dev/sdb7 34422400 7942172 24708608 25% /home
tmpfs 4079692 416068 3663624 11% /dev/shm
tmpfs 4079692 0 4079692 0% /sys/fs/cgroup
tmpfs 4079692 32 4079660 1% /tmp
tmpfs 815936 24 815912 1% /run/user/1001

2.4.2 Initramfs

初始ram文件系统,也称早期用户空间,典型用途是检测加载主用户空间文件系统所需的设备驱动程序,并从临时文件系统加载它们。
initramfs只须要包含访问根文件系统所需的模块; 它不须要包含一我的们想要使用的每一个模块。在init过程当中,udev将在稍后加载大多数模块。
Arch Linux使用内置initramfs的空存档(这是构建Linux时的默认存档)。
第一个提取的initramfs是在内核构建期间嵌入在内核二进制文件中的initramfs,而后提取可能的外部initramfs文件。
所以,外部initramfs中的文件会覆盖嵌入式initramfs中具备相同名称的文件。而后内核执行/init(在rootfs中)做为第一个进程。

2.4.3 查看initramfs

若是您对initramfs映像中的内容感到好奇,能够将其解压缩并查看其中的文件。
initramfs映像是一个SVR4 CPIO归档文件,经过find和bsdcpio命令生成,可选择使用内核理解的压缩方案进行压缩。
mkinitcpio包含一个名为的实用程序lsinitcpio,它将列出和/或提取initramfs图像的内容。

列出镜像中的文件:
$ lsinitcpio /boot/initramfs-linux.img

当前目录中提取:
$ lsinitcpio -x /boot/initramfs-linux.img

更加人性化的重要部分列表:
$ lsinitcpio -a /boot/initramfs-linux.img

2.4.4 建立initramfs

https://wiki.archlinux.org/index.php/Mkinitcpio
mkinitcpio是一个用于建立初始ramdisk环境的Bash脚本。
默认状况下,mkinitcpio脚本在内核安装或升级后生成两个镜像:默认镜像和跳过自动检测挂钩的回退镜像,所以包含了大量不须要的模块。
这是经过大多数内核包安装的.preset文件的PRESETS指令来完成的(例如,对于linux包含)。
预设是如何建立initramfs镜像的预约义定义,而不是每次都指定配置文件和输出文件。
例如,如下将(从新)生成由...提供的预设/etc/mkinitcpio.d//etc/mkinitcpio.d/linux.presetPRESETS=('default' 'fallback')-p--presetlinux包:
# mkinitcpio -p linux

附加配置文件位于/etc/mkinitcpio.conf并用于指定全部预设的全局选项。
的-P/ --allpresets开关指定的全部预置应在后再生的initramfs时被利用mkinitcpio.conf的变化。
用户可使用各类不一样的配置建立任意数量的initramfs镜像。必须在相应的引导加载程序配置文件中指定所需的镜像。

警告: .preset文件用于在内核更新后自动从新生成initramfs; 编辑时要当心。
mkinitcpio的主要配置文件是/etc/mkinitcpio.conf。
另外,预设定义由/etc/mkinitcpio.d目录中的内核包提供(例如/etc/mkinitcpio.d/linux.preset)。

生成自定义手动initcpio
用户可使用备用配置文件生成镜像。例如,如下内容将根据指示生成initramfs图像/etc/mkinitcpio-custom.conf并将其保存/boot/linux-custom.img。
# mkinitcpio -c /etc/mkinitcpio-custom.conf -g /boot/linux-custom.img

若是为当前正在运行的内核生成镜像,请将内核版本添加到命令行。您能够在中查看可用的内核版本/usr/lib/modules/。
# mkinitcpio -g /boot/linux-custom2.img -k 3.3.0-ARCH

用户能够修改配置文件中的六个变量:
MODULES 在运行任何引导挂钩以前加载的内核模块。
BINARIES 要包含在initramfs映像中的其余二进制文件。
FILES 要包含在initramfs映像中的其余文件。
HOOKS 挂钩是在初始ramdisk中执行的脚本。
COMPRESSION 用于压缩initramfs映像。
COMPRESSION_OPTIONS 传递给COMPRESSION程序的额外参数。强烈建议不要使用此设置。mkinitcpio将处理压缩机的特殊要求(例如传递--check=crc32给xz),而且误用很容易致使系统没法启动。

2.5 Linux系统中的initramfs

当前的Arch linux系统/boot/目录下
name type size
vmlinuz-linux DOS/Windows executable 5.8Mb
Initramfs-linux.img Raw disk image 8.7Mb
Initramfs-linux-fallback.img Raw disk image 29.3Mb

一些Linux的Live CD光盘文件里
Linux name type size
manjaro initramfs-x86_64.img Raw disk image 37Mb
ubuntu18 initrd CPIO archive 38Mb
mint191 initrd.lz
initrd.lz 解压后 initrd
Lzip archive
CPIO archive
35Mb
153Mb

2.6 cpio归档文件

https://en.wikipedia.org/wiki/Cpio
cpio最初设计用于以连续,连续的方式在磁带设备上存储备份文件存档。它不压缩任何内容,可是一般使用gzip或其余外部压缩器压缩生成的归档。
档案建立
在使用-o命令行标志启动的复制操做期间建立存档时,cpio从其标准输入通道读取文件和目录路径名,并将生成的存档字节流写入其标准输出。
所以,Cpio一般与生成要归档的文件列表的其余实用程序一块儿使用,例如查找程序。
生成的cpio存档是一系列文件和目录,它们链接成一个存档,由带有文件元信息的标题部分分隔,例如文件名,inode编号,全部权,权限和时间戳。按照惯例,归档的文件名一般被赋予文件扩展名cpio。
此示例使用find实用程序生成从当前目录开始的路径名列表,以建立目录树的存档:
$ find . -depth -print | cpio -o > /path/archive.cpio

提取
在由命令行标志i启动的拷入操做期间,cpio从其标准输入读取存档,并在操做系统的文件系统中从新建立存档文件。
命令行标志d告诉cpio根据须要构造目录。标志v(详细)列出提取时的文件名。
$ cpio -i -vd < archive.cpio
$ cpio -i -d /etc/fstab < archive.cpio

清单
列出cpio存档中包含的文件:
$ cpio -t < archive.cpio

复制
此示例将从当前目录开始的目录树复制到文件系统中的另外一个路径new-path,
保留文件修改时间(标志m),
根据须要建立目录(d),
无条件地替换任何现有文件(u),
同时生成标准输出的进度清单(v):
$ find . -depth -print | cpio -p -dumv new-path

3. 高级用户

3.1 制做本身的initramfs

http://blog.falconindy.com/articles/optmizing-bootup-with-mkinitcpio.html
使用mkinitcpio优化启动

在最简单的状况下,挂载根分区须要如下驱动程序:
存储总线(PATA,SATA,SCSI等)
块设备
文件系统

lsinitcpio很高兴地向你展现了图像上的确切内容。
'mkinitcpio -M'将扫描您的PCI总线并探测您的根文件系统,返回一个整洁的模块列表,没有依赖项。

https://wiki.archlinux.org/index.php/Minimal_initramfs
最小的initramfs

3.2 Initramfs编程

https://landley.net/writing/rootfs-programming.html
将一些可执行文件放入新的根文件系统。
使用mdev填充/dev
从rootfs切换到另外一个根文件系统

3.3 使用更新的工具

https://wiki.archlinux.org/index.php/Dracut
dracut建立内核使用的初始映像,用于预加载访问根文件系统所需的块设备模块(例如IDE,SCSI或RAID)。这可能会在不久的未来取代Arch Linux中的mkinitcpio。
https://dracut.wiki.kernel.org/index.php/Main_Page
注意:阅读邮件列表公告,了解可能使用Dracut替换Mkinitcpio。
https://lists.archlinux.org/pipermail/arch-dev-public/2019-May/029570.html
[arch-dev-public] Mkinitcpio replacement with Dracut
Giancarlo Razzolini grazzolini at archlinux.org
Tue May 21 02:41:40 UTC 2019
Mkinitcpio替换为Dracut的信息。有兴趣有能力的人能够多加关注,参与其中。

更多相关信息
https://landley.net/writing/rootfs-intro.html
https://wiki.debian.org/InitrdReplacementOptions
https://en.wikipedia.org/wiki/Initial_ramdisk
https://en.wikipedia.org/wiki/Tmpfs
https://en.wikipedia.org/wiki/Linux_startup_process
https://en.wikipedia.org/wiki/Initial_ramdisk

https://www.kernel.org/doc/Documentation/early-userspace/README  最后更新:2004-12-20
https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt   2005年10月17日

https://wiki.archlinux.org/index.php/Arch_boot_process#initramfs
https://wiki.archlinux.org/index.php/Mkinitcpio
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息