为什么需要initramfs?


17

我发现,如果选择jffssd作为文件系统(而非initramfs),内核大小将非常小(1.4 MB,而initramfs3.4MB)。这意味着initramfs占用相当大的空间。因此,如果可以的话,我将其完全删除,因此将具有非常小的内核,这正是我想要的。

我想到的基本问题是:为什么需要initramfs?没有任何初始文件系统,Linux内核不能启动吗?

我的最终应用程序将只进行计算和通信-根本没有存储。因此,没有文件系统的操作系统很有意义-至少对于我的应用程序而言。


2
没有initramfs,就无法做到。可能不需要附加的initramfs文件,但不管您做什么,内核都会包含它自己的空白。所以我不明白您的问题-您在谈论什么发行版本?您如何构建内核?您可以提供内核.config文件吗?这些非常重要。我怀疑您的发行版正在直接将其initramfs编译到内核中-因此填充了其中包含的否则为空的initramfs-但根据您提供的信息我不知道。
mikeserv

2
@mikeserv,显然是内置但未使用/未使用的initramfs无效。
psusi 2014年

好吧,@psusi内核文档不同意。而且我对此非常坚决,因为没有任何奥秘-仅/root此而已。唯一不同的是switch_root,即使对某些已加载内核模块采取了适当的预防措施,它也可以随时执行。Initramfs仅仅是磁盘映像-充满或没有,它在那里。而且,您永远不会没有它-毕竟这是您的根源。我认为,这不应该是一个谜,我不喜欢围绕它的所有不必要的混乱。
mikeserv

2
@mikeserv,不,/ root是根用户的主目录。rootfs是/,然后将实际根目录安装在它的顶部。您只是在争论语义。为了便于讨论,没有initramfs意味着引导加载程序必须在磁盘上加载文件并传递给内核。
psusi 2014年

是的,为了清楚起见,我只使用了/ root,但我会给你一个。但是,不是,它们不是语义,而是Linux内核的基本机制。这些是基本的东西。让我们尝试使它们正确。
mikeserv

Answers:


12

具有initramfs的大小增加不是由于ramfs驱动程序(只有几kB,并且无论如何需要其他东西),而是由于initramfs本身。initramfs包含汇编和挂载实际根文件系统所必需的程序。

Initramfs使/启动系统变得容易得多,并且在某些情况下(例如,加密)可以启动。强烈建议将其保留在具有大量可热插拔外围设备的PC式硬件上。另一方面,在没有任何initramfs的情况下引导嵌入式设备具有内核仅支持为其构建的特定硬件配置,这在很大程度上有意义。

当然,内核需要引导到文件系统:必须有某种方式可以使其加载要运行的任何应用程序。如果您什么也不打算运行,则最好关闭计算机电源。

如果您不想使用initramfs,只需告诉您的引导加载程序不要传递一个即可。也不包括一个在内核构建的输出,当然-这是如何发生,如果在所有的建筑-和引导程序相关的:例如,vmlinux并且bzImage不包括initramfs中(他们分别是原始和压缩的内核),但uImage(对于U-Boot)将内核和initramfs打包(如果有的话)。

(从技术上讲,如mikeserv所述,总是有一个initramfs-但默认情况下,它是一个空的134字节存档。您的构建过程,并包含用于挂载根文件系统的工具。)

请注意,initramfs是制作没有持久性数据的单应用程序系统的一种合理方法:将所有应用程序放入initramfs中,进行引导并保留它。这使组织持久性存储或启动映像更加容易(您所需要的只是内核和initramfs,它们可以捆绑在一起)。但是,这种方法有一些缺点:initramfs中的所有数据都将被永久存储在RAM中,并且您不能轻易地修改启动映像中的文件,因此必须重建归档文件。


如果您使用的是2.6或更高版本的Linux内核,则您具有initramfs。按照惯例,是否使用辅助initramfs映像是另一回事,但是initramfs不是可选的。
mikeserv 2014年

2
@mikeserv你有一个,是的。但是空的initramfs是花生。不必使用它(这要求它包含足够的程序来装入真实根,这在典型的嵌入式系统中以不可忽略的方式增加了大小)。
吉尔斯(Gillles)“所以-别再邪恶了”

还是要吃花生。而且我不知道什么时候我说不!询问者正在请求有关如何将其作为文件系统删除的信息-这是不可能的。
mikeserv

是的,它确实必须使用-没有initramfs,就没有根。曾经
mikeserv 2014年

8

LFS

initramfs的唯一目的是挂载根文件系统。initramfs是在普通根文件系统上可以找到的完整目录集。它被捆绑到单个cpio归档文件中,并使用几种压缩算法之一进行压缩。

...

在LFS环境中拥有initramfs的主要原因只有四个:从网络加载rootfs,从LVM逻辑卷加载initramfs,在需要密码的情况下具有加密的rootfs或为将rootfs指定为a标签或UUID。其他任何事情通常意味着内核配置不正确。

...

对于大多数发行版,内核模块是拥有initramfs的最大原因。在一般发行版中,存在许多未知数,例如文件系统类型和磁盘布局。在某种程度上,这与LFS相反,在LFS中,系统功能和布局是已知的,并且通常会构建自定义内核。在这种情况下,很少需要使用initramfs。

另一个来源www.kernel.org

除此之外,还有许多Linux系统,例如不使用initramfs的路由器。


1

您需要一个initramfs来进行更复杂的设置,例如网络引导,lvm或raid,因为它们需要一些用户模式实用程序来配置对根fs的访问。对于磁盘上的简单常规分区,只要将磁盘驱动程序内置到内核中,并通过设备路径而不是UUID指定root参数,那么就可以不使用initramfs。当然,设备路径可能会变化,这取决于您连接的即插即用设备(即usb),甚至只是随机的时序变化,这就是为什么几乎每个人都使用uuid和initramfs来提高可靠性的原因。


这也是不正确的。
mikeserv

6
@mikeserv,您的评论没有用。如果要声明这一点,则需要解释原因。
psusi 2014年

我已经完成了,或者说,内核文档构成了我答案的大约99%。
mikeserv

@mikeserv,是正确的。我在没有initramfs的情况下运行Gentoo linux已经有很多年了。
蒂姆(Tim)

1

这是一个古老的问题,但仍然没有一个可以接受的答案,因此我将其扔掉(我这里不是专家,我想自己解决这个问题。)

https://www.kernel.org/doc/Documentation/early-userspace/README(始终在底部表示自2004年以来未进行更新)。

内核当前有3种方式挂载根文件系统:

a)所有必需的设备和文件系统驱动程序都已编译到内核中,没有initrd。init / main.c:init()将基于root =选项和可选的init =调用prepare_namespace()来安装最终的根文件系统,以运行init / main.c:init末尾列出的其他初始化二进制文件。 ()。

b)一些作为模块构建并存储在initrd中的设备和文件系统驱动程序。initrd必须包含一个二进制文件“ / linuxrc”,该文件应该加载这些驱动程序模块。也可以通过linuxrc挂载最终的根文件系统,并使用ivot_root syscall。可以通过prepare_namespace()挂载并执行initrd。

c)使用initramfs。必须跳过对prepare_namespace()的调用。这意味着二进制文件必须完成所有工作。可以通过修改usr / gen_init_cpio.c或通过新的initrd格式(即cpio存档)将所述二进制文件存储到initramfs中。它必须称为“ / init”。该二进制文件负责执行prepare_namespace()会做的所有事情。

为了保持向后兼容性,/ init二进制文件仅在通过initramfs cpio归档文件提供时才运行。如果不是这种情况,init / main.c:init()将运行prepare_namespace()来挂载最终的根目录并执行预定义的init二进制文件之一。

就其价值而言,我相信Raspberry Pi等设备/发行版不使用initramfs。在某些情况下,内核位于根分区(由具有必需的fs模块的引导程序安装)。在其他情况下,例如在内核位于/boot分区上时,可以在安装rootfs之前直接访问同一分区上的initramfs。说了。

在某些情况下,可以将initramfs 内置到与内核相同的文件中,但并非总是如此。(a)似乎很清楚地表明,在某些情况下,不需要initramfs。


0

我发现以下解释更加清楚,

initramfs是一个根文件系统,已嵌入内核并在启动过程的早期阶段加载。它是initrd的后继者。它提供了早期的用户空间,可以执行内核在启动过程中无法轻易完成的工作。

使用initramfs是可选的。默认情况下,内核使用内置驱动程序初始化硬件,安装指定的根分区,加载已安装的Linux发行版的init系统。然后,init系统将加载其他模块并启动服务,直到最终允许您登录为止。这是一种很好的默认行为,对于许多用户而言已经足够。initramfs适用于有高级要求的用户;适用于需要尽早执行操作的用户,即使在挂载根分区之前也是如此。

以下是可以使用initramfs进行处理的一些示例:

  • 挂载根分区(用于加密,逻辑和其他特殊分区);
  • 提供一个简约的救援壳(如果出现问题);
  • 自定义引导过程(例如,打印欢迎信息,引导启动等);
  • 加载模块(例如第三方驱动程序);
  • 内核无法执行的任何操作(只要您可以在用户空间中执行(例如通过执行命令)即可)。如果您没有高级要求,则不需要initramfs。

-1

无论您做什么,都拥有initramfs没有它就无计可施-它是强加于您的唯一文件系统。从kernel.org

什么是rootfs?

Rootfs是的特殊实例ramfs(或tmpfs如果启用的话),该 实例始终存在于2.6系统中。无法rootfs以无法杀死init进程的相同原因卸载。与其使用特殊的代码来检查和处理一个空列表,不如让内核仅确保某些列表不会为空,它变得更小,更简单。

大多数系统只是挂载另一个文件系统rootfs而忽略它。一个空的ramfs实例占用的空间很小。

如果启用了* CONFIG_TMPFS *,默认情况下rootfs将使用tmpfs代替ramfs。要强制ramfs,请添加"rootfstype=ramfs"到内核​​命令行。

什么是initramfs?

所有2.6 Linux内核都包含gzip压缩"cpio"格式的归档文件,该文件在内核启动时提取到rootfs其中 提取后,内核检查是否rootfs包含文件"init"如果包含则将其作为 PID 1执行 如果找到该文件则该init过程负责使系统其余部分正常运行,包括查找和安装实际的根设备(如果有的话)。 如果在将嵌入式归档文件提取到其中之后rootfs不包含init程序cpio,则内核将陷入较旧的代码中,以查找并挂载根分区,然后执行其中的一些变体/sbin/init

所有这一切都与旧的initrd在以下方面有所不同:

  • 旧的initrd始终是一个单独的文件,而initramfs归档文件已链接到linux内核映像中。 (目录linux-* / usr用于在构建过程中生成此归档文件。)

  • 旧的initrd文件是gzip压缩的文件系统映像(采用ext2等某种文件格式,需要在内核中内置驱动程序),而新的initramfs归档文件是gcp压缩的cpio归档文件(仅比tar更简单,请参见cpio(1))。和文档/early-userspace/buffer-format.txt)。内核的cpio提取代码不仅很小,而且是__init文本和数据,可以在引导过程中将其丢弃。

  • 由旧的initrd(称为/ initrd,而不是/ init)运行的程序进行了一些设置,然后返回内核,而initramfs的init程序预计不会返回内核。(如果/ init需要交出控制权,则可以使用新的根设备来超载/并执行另一个init程序。请参见下面的switch_root实用程序。)

  • 切换另一个根设备时,initrd将枢轴化root,然后卸载虚拟磁盘。但是initramfs是rootfs:您不能pivot_root rootfs,也不能将其卸载。 而是从rootfs中删除所有内容以释放空间(找到-xdev / -exec rm'{}'';'),用新的根目录(cd / newmount; mount --move ./; chroot。)覆盖rootfs,将stdin / stdout / stderr附加到新的/ dev / console并执行新的init。

由于这是一个非常棘手的过程(需要删除命令才能运行它们),因此klibc软件包引入了一个帮助程序(utils / run_init.c)为您完成所有这些操作。大多数其他软件包(例如busybox)已将此命令命名为“ switch_root”。

填充initramfs:

2.6内核构建过程始终会创建gzip cpio格式的initramfs存档,并将其链接到生成的内核二进制文件中。 默认情况下,此存档为空(在x86上消耗134个字节)。

可以使用配置选项CONFIG_INITRAMFS_SOURCE(在menuconfig中的常规设置中,并且位于usr / Kconfig中)来指定initramfs归档文件的源,该文件将自动合并到生成的二进制文件中。此选项可以指向现有的gzip压缩cpio归档文件,包含要归档文件的目录或文本文件规范,例如以下示例:

  dir /dev 755 0 0
  nod /dev/console 644 0 0 c 5 1
  nod /dev/loop0 644 0 0 b 7 0
  dir /bin 755 1000 1000
  slink /bin/sh busybox 777 0 0
  file /bin/busybox initramfs/busybox 755 0 0
  dir /proc 755 0 0
  dir /sys 755 0 0
  dir /mnt 755 0 0
  file /init initramfs/init.sh 755 0 0

运行“ usr / gen_init_cpio”(在内核构建后)以获取记录上述文件格式的用法消息。

配置文件的一个优点是不需要root访问权限即可设置权限或在新档案中创建设备节点。(请注意,这两个示例“文件”条目期望在linux-2.6。*目录下名为“ initramfs”的目录中找到名为“ init.sh”和“ busybox”的文件。有关信息,请参见Documentation / early-userspace / README。更多细节。)

内核不依赖外部cpio工具。如果您指定目录而不是配置文件,则内核的构建基础结构会从该目录创建一个配置文件(usr / Makefile调用scripts / gen_initramfs_list.sh),然后继续使用该配置文件打包该目录(将其输入usr / gen_init_cpio,它是从usr / gen_init_cpio.c创建的)。内核的构建时cpio创建代码是完全独立的,内核的启动时提取程序也是(显然)独立的。


1
您可以在没有initramfs的情况下启动。您的答案阐述了initramfs的优点,但这不适用于典型的嵌入式系统,甚至在建议使用initramfs的台式机或服务器上也不是必需的。
吉尔斯(Gilles)'“ SO-别再邪恶了”

@吉尔斯-不,你不能。无论您做什么,都拥有initramfs。它已编译到内核中-现在,您的内核,我的内核以及我们所有的内核。阅读内核文档-我的整个帖子都是复制粘贴。你不对 您如何对官方文档提出异议?
mikeserv 2014年

1
我不反对官方文档,我反对您从中得出的结论。您正在阅读说明如何使用initramfs的文档。它没有说明必须使用initramfs。
吉尔斯(Gilles)'所以

@Gilles如果这还不够好:“ 2.6内核构建过程总是创建gzip cpio格式的initramfs存档并将其链接到生成的内核二进制文件中。默认情况下,此存档为空(在x86上消耗134字节)。 “ 我能做得更好。以上是2或3分钟的网络搜索。
mikeserv 2014年

3
我已经阅读了文档。我这样做是为了谋生。这不是意见问题。总有一个initramfs,但不一定用于引导。对于这种情况,我找不到合适的内核结构解释,大概是因为这是经典的情况,因此不值得解释。主要逻辑在do_mounts.c-具体来说prepare_namespace,其中saved_root_name包含root=命令行参数。
吉尔(Gilles)'所以
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.