¿Diferencia en la ejecución de init con initramfs incrustado versus externo?


10

Estoy construyendo un sistema Linux muy mínimo que solo consta del kernel (v4.1-rc5) y un initramfs poblado con busybox (v1.23.2). Funciona bien en su mayor parte, pero observo una diferencia en el comportamiento de la ejecución del comando en / init si estoy usando un initramfs incrustado frente a uno externo.

El script / init es:

#!/bin/sh

dmesg -n 1

mount -t devtmpfs none /dev
mount -t sysfs none /sys
mount -t proc none /proc
echo "Welcome"
while true
do
    setsid cttyhack /bin/sh
done

Luego configuro la opción CONFIG_INITRAMFS_SOURCE en el kernel .config en el directorio que contiene todas las carpetas para initramfs, o ejecuto

find . | cpio -H newc -o | gzip > ../rootfs.cpio.gz

para construirlo

Cuando compilo el núcleo, con o sin el conjunto CONFIG_INITRAMFS_SOURCE, termino con dos variantes de mi sistema:

  1. bzImage con initramfs incrustado

  2. bzImage + rootfs.cpio.gz (initramfs externo)

cuando ahora empiezo a usar qemu

qemu-system-x86_64 -enable-kvm -kernel bzImage

o

qemu-system-x86_64 -enable-kvm -kernel bzImage -initrd rootfs.cpio.gz

Tengo la siguiente diferencia de comportamiento:

con la versión 2 (initramfs externo) todo funciona bien, se muestra "Bienvenido" y aparece un mensaje. Sin embargo, con la versión 1 (initramfs incrustado) recibo la advertencia

unable to open an initial console

"Bienvenido" no se muestra y recibo mi mensaje.

Hasta donde entiendo el proceso, esas dos versiones de initramfs deberían contener los mismos archivos, ya que lo compilo (o hago que el núcleo lo construya) desde una carpeta idéntica.

Me pregunto si alguien puede ayudarme con una explicación de este comportamiento.

* ACTUALIZACIÓN *

Como dijo mikeserv en los comentarios, el núcleo incluye un mínimo de initramfs incrustado por defecto. Esto todavía está presente cuando se usa uno externo, pero se sobrescribe si incrusta el suyo. Descubrí que, contrario a la especificación, esto no está vacío, sino que contiene una carpeta de desarrollo, una carpeta raíz y el dispositivo / dev / console. Este dispositivo luego se usa cuando se usa un initramfs externo, pero se sobrescribe si incrusta el suyo. Por lo tanto, debe incluir el dispositivo / dev / console en su fuente initramfs mknod -m 622 initramfs_src/dev/console c 5 1cuando incruste el suyo.

¡Muchas gracias a mikeserv, frostschutz y JdeBP por ayudarme a entenderlo!


¿Cuáles son los permisos establecidos /dev/consoleen su uno incorporado? Creo que la diferencia podría estar en quién empaca en los dos casos.
mikeserv

Una pregunta similar es, por supuesto, stackoverflow.com/questions/10437995 .
JdeBP

@mikeserv el dispositivo de consola tiene permisos y propiedad idénticos en ambas compilaciones.
clw

@JdeBP No estoy seguro de si es tan similar, ya que en ambos casos arranco, recibo un mensaje y tengo un dispositivo de consola. Solo que en un init ejecuta el eco y en el otro no puede.
clw

1
¿Cómo podrían los permisos haber sido los mismos en initramfs si ni siquiera lo tenía?
mikeserv

Respuestas:


2

¿Son realmente idénticos?

El incorporado puede encontrarlo /usr/src/linux/usr/initramfs_data.cpio.gzo extraerlo de bzImage como se describe aquí: https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging

Si usa ese incorporado y lo usa como externo, ¿funciona?

Si aún es diferente, ¿el núcleo en sí es idéntico? (comparar /proc/config.gzpara ambos)

Debería haber alguna diferencia. No soy consciente de que al núcleo le importa de dónde provienen los initramfs. Prefiero sospechar qemude usar diferentes configuraciones al pasar el -initrdparámetro ...

En una nota al margen, me /initparece que está generando infinitas conchas para mí. setsidno es exec. ¿Me equivoco?


1
Esta respuesta parece ser todas las preguntas.
JdeBP

1
@JdeBP: ¡No estás pensando en cuarta dimensión!
frostschutz

1
@frostschutz ¡Muchas gracias por tu respuesta! ¡Cuando uso el initramfs que el núcleo construye (usr / initramfs_data.cpio.gz) como externo, también funciona bien! Además, cuando proporciono el núcleo que se compiló con los initramfs incrustados con uno externo, aparece la advertencia, aunque el externo debe sobrescribir el incrustado ( kernel.org/doc/Documentation/filesystems/… ). Entonces, probablemente tampoco sea qemu -initrd sino algo dentro del núcleo mismo. Sin embargo, no cambié nada más que CONFIG_INITRAMFS_SOURCE ..
clw

@frostschutz Respondiendo a On a sidenote, your /init looks like its spawning infinite shells to me. setsid is not exec. Am I wrong?: El bucle imita a getty o herramientas similares, ya que llama a los shbloques hasta que sale ese shell.
stefanjunker

@stefanjunker y eso estaría bien, excepto que setsid no bloquea en absoluto ...
frostschutz

1

También puede interesarle cómo Buildroot 2018.02 trata esto.

Cada vez que usa initramfs ( BR2_TARGET_ROOTFS_INITRAMFS=y) o initrd ( BR2_TARGET_ROOTFS_CPIO=n), agrega lo siguiente /inita sus rootfs https://github.com/buildroot/buildroot/blob/2018.02/fs/cpio/init

#!/bin/sh
# devtmpfs does not get automounted for initramfs
/bin/mount -t devtmpfs devtmpfs /dev
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console
exec /sbin/init "$@"

La copia la realiza https://github.com/buildroot/buildroot/blob/2018.02/fs/cpio/cpio.mk :

# devtmpfs does not get automounted when initramfs is used.
# Add a pre-init script to mount it before running init
define ROOTFS_CPIO_ADD_INIT
    if [ ! -e $(TARGET_DIR)/init ]; then \
        $(INSTALL) -m 0755 fs/cpio/init $(TARGET_DIR)/init; \
    fi
endef

También es útil saber que la ruta de inicio es /initpara initramfs, a diferencia de lo /sbin/initcontrario: ¿qué puede hacer que pasar init = / path / to / program al kernel no inicie el programa como init?

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.