¿Puede el proceso init ser un script de shell en Linux?

14

Estaba siguiendo un tutorial sobre cómo configurar un initramfs personalizado donde dice:

Lo único que falta es / init, el ejecutable en la raíz de initramfs que ejecuta el núcleo una vez que se carga. Debido a que sys-apps / busybox incluye un shell completamente funcional, esto significa que puede escribir su binario / init como un simple script de shell (en lugar de hacerlo una aplicación complicada escrita en Assembler o C que debe compilar).

y da un ejemplo de init como un script de shell que comienza con #!/bin/busybox sh

Hasta ahora, tenía la impresión de que init es el proceso principal que se inicia y que todos los demás procesos del espacio de usuario son eventualmente hijos de init. Sin embargo, en el ejemplo dado, el primer proceso es en realidad a bin/busybox/ shpartir del cual se genera init posterior.

¿Es esta una correcta interacción? Si, por ejemplo, tuviera un intérprete disponible en ese momento, ¿podría escribir init como un script de Python, etc.?

El Ingeniero Significante
fuente

Respuestas:

12

init no se "genera" (como un proceso secundario), sino más bien me execgustaría:

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

execreemplaza todo el proceso en su lugar. El init final sigue siendo el primer proceso (pid 1), a pesar de que fue precedido por los de Initramfs.

Initramfs /init, que es un script de shell de Busybox con pid 1, execs a Busybox switch_root(por lo que ahora switch_rootes pid 1); Este programa cambia tus puntos de montaje, así /mnt/rootque será el nuevo /.

switch_roota continuación, de nuevo execS para /sbin/initsu sistema de ficheros raíz real; por lo tanto, hace que su sistema init real sea el primer proceso con pid 1, que a su vez puede generar cualquier número de procesos secundarios.

Ciertamente, también podría hacerse con un script de Python, si de alguna manera lograras hornear Python en tus 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 binarios de script ( CONFIG_BINFMT_SCRIPT=y), o más bien en ese caso, tendría que iniciar el intérprete directamente y hacer que cargue su script de alguna manera.

Frostschutz
fuente
/no se desvanece en el aire : se monta (aunque generalmente todo su contenido se elimina antes de ahorrar memoria) . Aún está ahí . switch_rootrealiza la llamada al sistema switchroot, que es lo que proporcionaron los desarrolladores del kernel cuando cambiaron el proceso de arranque en el kernel 2.6.algo que requiere initramfs. Es el núcleo que hace la magia.
mikeserv
1
Un switchrootsyscall de hecho sería una novedad para mí. ¿Tiene usted una fuente para eso? Si observa el código fuente switch_root.c, parece ser un proceso bastante manual, y es el mismo que se describe en Documentation / filesystems / ramfs-rootfs-initramfs.txt. Además, si eliminas todo y lo montas, está casi desaparecido en este punto, ¿no crees?
frostschutz
pivot_root, por otro lado, es un syscall. Sin switch_rootembargo, no se usa y no se puede usar sin saltar a través de algunos aros, y de cualquier manera no importa nada para esta respuesta, así que simplemente la eliminé por completo. Lástima, pensé que la magia y desaparecer en el aire funcionaba muy bien ...
:-P
Bueno, tal vez me hice una idea equivocada switch_root, por lo que lo siento, y gracias por mostrarme, pero de todos modos no desaparece. La raíz initramfs persiste y siempre está ahí para todos, es root.
mikeserv
1
Como dicen los documentos que vinculó : Pero initramfs es rootfs: no puede pivot_root rootfs, ni desmontarlo. En su lugar, elimine todo de rootfs para liberar el espacio ( find -xdev / -exec rm '{}' ';'), supere rootfs con el nuevo root ( cd /newmount; mount --move . /; chroot .), adjunte stdin / stdout / stderr a la nueva / dev / console y ejecute el nuevo init.
mikeserv
4

El syscall ejecutivo del kernel de Linux no entiende los shebangs de forma nativa

Cuando el archivo ejecutado comienza con los bytes mágicos #!, le dicen al núcleo que lo use #!/bin/shcomo:

  • hacer y execllamar 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 userland normal con:

./myscript.sh

Si el archivo hubiera comenzado con los bytes mágicos en .ELFlugar de #!, el núcleo elegiría el cargador ELF en su lugar para ejecutarlo.

Más detalles en: ¿Por qué la gente escribe el #! / Usr / bin / env python shebang en la primera línea de un script de Python? El | Desbordamiento de pila

Una vez que tenga esto en mente, se hace fácil aceptar que /initpuede ser cualquier cosa que el núcleo pueda ejecutar, incluido un script de shell, y también por qué /bin/shserá 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

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
fuente