初始化过程可以是Linux中的Shell脚本吗?


14

我正在阅读有关设置自定义initramfs教程,其中指出:

唯一缺少的是/ init,它是initramfs根目录中的可执行文件,一旦加载,内核便会执行该可执行文件。由于sys-apps / busybox包含功能齐全的外壳程序,因此这意味着您可以将/ init二进制文件编写为简单的外壳程序脚本(而不是使其成为必须用汇编程序或C语言编写的复杂应用程序)。

并给出了init作为以以下内容开头的shell脚本的示例 #!/bin/busybox sh

到目前为止,我的印象是init是启动的主要过程,而所有其他用户空间过程最终都是init的子级。但是,在给定的示例中,第一个过程实际上是bin/busybox/ sh从中产生后来的init的。

这是正确的做法吗?例如,如果当时我有可用的解释器,那么我可以将初始化编写为Python脚本等吗?

Answers:


12

init不是“产生”的(作为子进程),而是exec这样的:

# Boot the real thing.
exec switch_root /mnt/root /sbin/init

exec替换整个过程。最终的init仍然是第一个过程(pid 1),即使它先于Initramfs中的过程也是如此。

Initramfs /init是Busybox的shell脚本,具有pid 1,execs到Busybox switch_root(所以现在switch_root是pid 1);这个程序改变了你的挂载点,因此/mnt/root将会是新的/

switch_root然后再次exec/sbin/init您的真实根文件系统;因此,它使您的实际初始化系统成为pid 1的第一个进程,而该进程又可能会产生任意数量的子进程。

如果您设法以某种方式将Python烘焙到Initramfs中,那么当然可以使用Python脚本来完成。尽管无论如何您都不打算包括busybox,但是您必须费心地重新实现其某些功能(例如switch_root和,以及通常使用简单命令即可完成的所有其他操作)。

但是,它不适用于不允许脚本二进制文件(CONFIG_BINFMT_SCRIPT=y)的内核,或者在这种情况下,您必须直接启动解释器并以某种方式使其加载脚本。


/不会消失在稀薄的空气中 -它被安装在上面(尽管通常在保存内存之前,所有内容都已删除)。它仍然在那里switch_root进行系统调用switchroot-这是内核开发人员在内核2.6中更改引导过程时提供的内容。某些需要initramfs的东西。神奇的是内核。
mikeserv

1
一个switchroot系统调用确实是我这个消息。您有资料来源吗?如果您查看switch_root.c源代码,它似乎是一个手动过程,与Documentation / filesystems / ramfs-rootfs-initramfs.txt中描述的过程相同。另外,如果您删除所有内容并将其挂载,那么此时它几乎消失了,不是吗?
frostschutz 2014年

pivot_root另一方面,是系统调用。但是,它switch_root并没有被使用,也不能不经过一些箍而​​被使用,无论哪种方式,这个答案都无关紧要,所以我将其完全删除了。太糟糕了,我认为魔术和消失在空中的效果真的很好... :-P
frostschutz 2014年

好吧,也许我有一个错误的主意switch_root-很抱歉,我感谢您向我展示-但是它仍然没有消失。initramfs root一直存在,并且始终存在于每个人中-它 root。
mikeserv

1
正如您链接到文档所说但initramfs是rootfs:您不能pivot_root rootfs,也不能卸载它。而是从rootfs中删除所有内容以释放空间(find -xdev / -exec rm '{}' ';'),用新的root(cd /newmount; mount --move . /; chroot .)覆盖rootfs ,将stdin / stdout / stderr附加到新的/ dev / console并执行新的init。
mikeserv 2014年

4

Linux内核的exec syscall会自然地破坏shebangs

当执行的文件以magic bytes开头时#!,它们告诉内核将其#!/bin/sh用作:

  • 做和exec系统调用
  • 具有可执行文件 /bin/sh
  • 并使用CLI参数:当前脚本的路径

这与运行常规userland shell脚本并执行以下操作完全相同:

./myscript.sh

如果文件以魔术字节.ELF而不是开头#!,则内核将选择ELF加载程序来运行它。

有关更多详细信息,请参见:人们为什么在Python脚本的第一行写#!/ usr / bin / env python shebang?| 堆栈溢出

一旦意识到这一点,就很容易接受/init内核可以执行的任何事情,包括外壳程序脚本,以及/bin/sh在这种情况下为什么将成为第一个可执行文件。

对于那些想要尝试的人来说,这是一个最小的可运行示例:https : //github.com/cirosantilli/linux-kernel-module-cheat/tree/cbea7cc02c868711109ae1a261d01fd0473eea0b#custom-init

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.