The*_*eer 16 linux init-script init
我正在阅读有关设置自定义 initramfs的教程,其中指出:
唯一缺少的是 /init,它是 initramfs 根目录中的可执行文件,一旦加载内核就会执行。因为 sys-apps/busybox 包含一个功能齐全的 shell,这意味着您可以将 /init 二进制文件编写为一个简单的 shell 脚本(而不是使它成为一个必须编译的用汇编程序或 C 编写的复杂应用程序)。
并给出了一个以 init 开头的 shell 脚本示例 #!/bin/busybox sh
到目前为止,我的印象是 init 是启动的主进程,所有其他用户空间进程最终都是 init 的子进程。但是,在给定的示例中,第一个进程实际上是bin/busybox/ sh从中产生后来的 init 的。
这是正确的解释吗?例如,如果我当时有一个可用的解释器,我可以将 init 编写为 Python 脚本等吗?
fro*_*utz 14
init 不是“生成”的(作为子进程),而是exec像这样:
# Boot the real thing.
exec switch_root /mnt/root /sbin/init
Run Code Online (Sandbox Code Playgroud)
exec将整个过程替换到位。最后的 init 仍然是第一个进程(pid 1),即使它在 Initramfs 之前。
Initramfs /init,这是一个带有pid 1的Busybox shell脚本,execs到Busybox switch_root(所以现在switch_root是pid 1);该程序会更改您的挂载点,因此/mnt/root新的/.
switch_root然后再次exec访问/sbin/init您真正的根文件系统;因此,它使您真正的 init 系统成为第一个 pid 为 1 的进程,这反过来可能会产生任意数量的子进程。
当然,如果您以某种方式设法将 Python 烘焙到您的 Initramfs 中,它也可以用 Python 脚本完成。尽管如果您无论如何不打算包含 busybox,您将不得不煞费苦心地重新实现它的一些功能(例如switch_root,以及您通常使用简单命令执行的所有其他操作)。
但是,它不适用于不允许脚本二进制文件 ( CONFIG_BINFMT_SCRIPT=y) 的内核,或者在这种情况下,您必须直接启动解释器并使其以某种方式加载您的脚本。
Linux 内核的 exec 系统调用本机理解 shebangs
当执行的文件以魔法字节开始时#!,它们告诉内核使用#!/bin/sh:
exec系统调用/bin/sh这与运行常规用户空间 shell 脚本时发生的情况完全相同:
./myscript.sh
Run Code Online (Sandbox Code Playgroud)
如果文件以魔法字节.ELF而不是开头#!,内核将选择 ELF 加载器来运行它。
更多细节在:为什么人们在 Python 脚本的第一行写 #!/usr/bin/env python shebang?| 堆栈溢出
一旦你记住了这一点,就很容易接受/init内核可以执行的任何东西,包括 shell 脚本,以及为什么/bin/sh在这种情况下将成为第一个可执行文件。
对于那些想要尝试的人,这是一个最小的可运行示例:https : //github.com/cirosantilli/linux-kernel-module-cheat/tree/cbea7cc02c868711109ae1a261d01fd0473eea0b#custom-init
| 归档时间: |
|
| 查看次数: |
8130 次 |
| 最近记录: |