init wird nicht "erzeugt" (als untergeordneter Prozess), sondern exec
würde das mögen:
# Boot the real thing.
exec switch_root /mnt/root /sbin/init
exec
ersetzt den gesamten Prozess an Ort und Stelle. Die letzte Init ist immer noch der erste Prozess (PID 1), obwohl ihm die in den Initramfs vorangegangen sind.
Die Initramfs /init
, das ein Busybox-Shell-Skript mit PID 1, exec
ist s an Busybox switch_root
(also jetzt switch_root
ist PID 1); Dieses Programm ändert Ihre Einhängepunkte so /mnt/root
wird der neue /
.
switch_root
dann wieder exec
s bis /sbin/init
Ihres echten Root-Dateisystems; Dadurch wird Ihr reales Init-System zum ersten Prozess mit PID 1, der wiederum eine beliebige Anzahl von untergeordneten Prozessen hervorbringen kann.
Natürlich könnte es genauso gut mit einem Python-Skript gemacht werden, wenn Sie es irgendwie geschafft hätten, Python in Ihr Initramfs zu backen. Wenn Sie jedoch nicht vorhaben, busybox ohnehin einzubinden, müssten Sie einige ihrer Funktionen mühsam neu implementieren (wie switch_root
, und alles andere, was Sie normalerweise mit einem einfachen Befehl tun würden).
Es funktioniert jedoch nicht auf Kerneln, die keine Skript-Binärdateien zulassen (CONFIG_BINFMT_SCRIPT=y
), oder besser gesagt, in einem solchen Fall müssten Sie den Interpreter direkt starten und ihn irgendwie dazu bringen, Ihr Skript zu laden.
Der exec syscall des Linux-Kernels versteht Shebangs von Haus aus
Wenn die ausgeführte Datei mit den magischen Bytes #!
beginnt , weisen sie den Kernel an, #!/bin/sh
zu verwenden als:
- do und
exec
Systemaufruf - mit ausführbarem
/bin/sh
- und mit CLI-Argument:Pfad zum aktuellen Skript
Dies ist genau dasselbe, was passiert, wenn Sie ein reguläres Userland-Shell-Skript mit:
ausführen./myscript.sh
Wenn die Datei mit den magischen Bytes .ELF
begonnen hätte statt #!
, würde der Kernel stattdessen den ELF-Loader auswählen, um ihn auszuführen.
Weitere Details unter:Warum schreiben die Leute das #!/usr/bin/env python shebang in die erste Zeile eines Python-Skripts? | Stapelüberlauf
Sobald Sie dies im Hinterkopf haben, wird es einfach, diese /init
zu akzeptieren kann alles sein, was der Kernel ausführen kann, einschließlich eines Shell-Skripts, und auch warum /bin/sh
wird in diesem Fall die erste ausführbare Datei sein.
Hier ist ein lauffähiges Minimalbeispiel für diejenigen, die es ausprobieren möchten:https://github.com/cirosantilli/linux-kernel-module-cheat/tree/cbea7cc02c868711109ae1a261d01fd0473eea0b#custom-init