init no se "genera" (como un proceso secundario), sino exec
Me gustaría esto:
# Boot the real thing.
exec switch_root /mnt/root /sbin/init
exec
reemplaza todo el proceso en su lugar. El init final sigue siendo el primer proceso (pid 1), aunque fue precedido por los de Initramfs.
El Initramfs /init
, que es un script de shell de Busybox con pid 1, exec
s a Busybox switch_root
(así que ahora switch_root
es pid 1); este programa cambia sus puntos de montaje por lo que /mnt/root
será el nuevo /
.
switch_root
luego otra vez exec
s a /sbin/init
de su sistema de archivos raíz real; por lo tanto, hace que su sistema de inicio real sea el primer proceso con pid 1, que a su vez puede generar cualquier cantidad de procesos secundarios.
Ciertamente, también podría hacerse con una secuencia de comandos de Python, si de alguna manera lograra integrar Python en su Initramfs. Aunque si no planea incluir busybox de todos modos, tendría que volver a implementar minuciosamente algunas de sus funciones (como switch_root
y todo lo demás que normalmente haría con un simple comando).
Sin embargo, no funciona en núcleos que no permiten archivos binarios de secuencias de comandos (CONFIG_BINFMT_SCRIPT=y
), o más bien, en tal caso, tendría que iniciar el intérprete directamente y hacer que cargue su script de alguna manera.
La llamada al sistema ejecutiva del kernel de Linux entiende shebangs de forma nativa
Cuando el archivo ejecutado comienza con los bytes mágicos #!
, le dicen al kernel que use #!/bin/sh
como:
- hacer y
exec
llamada al sistema - con ejecutable
/bin/sh
- y con argumento CLI:ruta al script actual
Esto es exactamente lo mismo que sucede cuando ejecuta un script de shell de usuario regular con:
./myscript.sh
Si el archivo hubiera comenzado con los bytes mágicos .ELF
en lugar de #!
, el núcleo elegiría el cargador ELF para ejecutarlo.
Más detalles en:¿Por qué la gente escribe #!/usr/bin/env python shebang en la primera línea de un script de Python? | Desbordamiento de pila
Una vez que tenga esto en mente, será fácil aceptar que /init
puede ser cualquier cosa que el kernel pueda ejecutar, incluido un script de shell, y también por qué /bin/sh
será el primer ejecutable en ese caso.
Aquí hay un ejemplo ejecutable mínimo para aquellos que quieran probarlo:https://github.com/cirosantilli/linux-kernel-module-cheat/tree/cbea7cc02c868711109ae1a261d01fd0473eea0b#custom-init