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

Linux-initramfs的更多相关文章

  1. Linux initramfs说明

    1.前言 最近在尝试对手头的开发板进行移植,此处记录initramfs挂载的基本流程,记录一下,以备后查.分析时是基于linux3.4.2 2. rootfs的挂载 start_kernel-> ...

  2. Linux 驱动开发

    linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...

  3. 基于 debootstrap 和 busybox 构建 mini ubuntu

    基于 debootstrap 和 busybox 构建 mini ubuntu 最近的工作涉及到服务器自动安装和网络部署操作系统,然后使用 ansible 和 saltsatck 进行配置并安装 op ...

  4. 搭建基于qemu + eclipse的kernel调试环境(by quqi99)

    作者:张华  发表于:2016-02-06版权声明:能够随意转载.转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 ( http://blog.csdn.net/quqi99 ) 使用q ...

  5. 内核移植和文件系统制作(2):linux内核最小系统和initramfs文件系统

    linux内核最小系统,使用内核版本:https://www.kernel.org/pub/linux/kernel/v3.0/linux-3.8.1.tar.bz2 1,FL2440板子的基本硬件: ...

  6. Linux内核3.0移植并基于Initramfs根文件系统启动

    Linux内核移植与启动 Target borad:FL2440 Bootloader:U-boot-2010.09 交叉编译器:buildroot-2012.08 1.linux内核基础知识 首先, ...

  7. 从ramdisk根文件系统启动Linux成功,及使用initramfs启动linux

    下面两篇文章是ARM9论坛上的讲解ramdisk文件系统的很不错的文章 今天做了个试验,让Linux2.6.29.4从ramdisk根文件系统启动成功,总结一下. 其中涉及的内容较多,很多东西不再详述 ...

  8. linux中的rootfs/initrd/ramfs/initramfs

    什么是ramfs?ramfs是空间规模动态变化的RAM文件系统.它非常简单,是用来实现Linux缓存机制(缓存page cache and dentry cache)的文件系统.通常情况下,Linux ...

  9. 基于mini2440嵌入式Linux根文件系统制作(Initramfs和nfs两种跟文件系统)

    嵌入式系统由三部分构成: 1.bootoader---bootparameters---2.kernel 3.Root-filesysytem 一个内核可以挂载多个文件系统,但是有一个根文件系统所以叫 ...

  10. 【嵌入式 Linux文件系统】如何使用Initramfs文件系统

    (1)#cd ../rootfs/ #ln -s ./bin/busybox init 创建软链接 (2)进入Linux内核 #make menuconfig General setup-->I ...

随机推荐

  1. python中 with 的作用

    with是 Python2.5 引入的一个新语法,它是一种上下文管理协议,目的在于从流程中吧 try...except 和 finally 关键字和资源释放相关代码统统去掉,简化 try...exce ...

  2. asp.net core配置下载文件

    asp.net core的wwwroot文件夹下默认时保存静态文件的地方,外面可以直接访问,但是如果是一些无法识别的后缀文件,如(.apk),会报错404 如果想要实现下载这些文件,在配置静态文件中间 ...

  3. 【PAT甲级】1012 The Best Rank (25 分)

    题意: 输入两个整数N,M(<=2000),接着分别输入N个学生的ID,C语言成绩,数学成绩和英语成绩. M次询问,每次输入学生ID,如果该ID不存在则输出N/A,存在则输出该学生排名最考前的一 ...

  4. IDEA 在同一工作空间创建多个项目

    1.创建项目 二..创建工作空间 JavaWorkspace 1.File-> New Project -> 创建工作空间 JavaWorkspace,并 顺便创建项目 JavaOne 2 ...

  5. 「TJOI2013」最长上升子序列

    「TJOI2013」最长上升子序列 传送门 这个 \(\text{DP}\) 应该都会撒: \[dp_i = \max_{j < i,a_j < a_i}\left\{dp_j\right ...

  6. Django学习 之 HTTP与WEB为Django做准备

    一.HTTP 1.HTTP 简介 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准. ...

  7. 2020年java架构师是什么-java架构师基本要求

    Java系统架构师是一个既必须掌控整体又必须洞察部分瓶颈并根据实际的业务流程情景得出解决方法的团队领导型角色.一个架构师得必须充足的创造力,可以各种各样目标要求开展不一样层面的拓展,为目标顾客出示更加 ...

  8. MyBatis的2个核心对象:SqlSessionFactory、SqlSession

    SqlSessionFactory SqlSessionFactory是单个数据库映射关系经过编译后的内存镜像,主要作用是创建SqlSession. InputStream inputStream = ...

  9. apache服务器本质上说是一个TCP socket服务

    apache服务器本质上说是一个TCP socket服务,socket模型如下:  下面以worker MPM来说明apache代码中相应处理的位置在哪里: (以apache httpd 2.2.23 ...

  10. Ubuntu安装docker并修改镜像仓库

    首先切换到root用户 安装docker wget -qO- https://get.docker.com/ | sh 使用docker -v查看docker版本 创建daemon.json 并键入以 ...