Diferença na execução do init com initramfs integrados vs. externos?

9

Estou construindo um sistema Linux muito minimalista que consiste apenas no kernel (v4.1-rc5) e um initramfs preenchido com busybox (v1.23.2). Ele funciona bem na maior parte, mas eu observo uma diferença no comportamento da execução de comandos em / init, quer eu esteja usando um initramfs incorporado contra um externo.

O script / init é:

#!/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

Então eu defino a opção CONFIG_INITRAMFS_SOURCE no kernel .config para o diretório que contém todas as pastas do initramfs, ou eu corro

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

para construí-lo.

Quando eu compilo o kernel, com ou sem CONFIG_INITRAMFS_SOURCE, acabo com duas variantes do meu sistema:

  1. bzImage com o initramfs incorporado

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

quando eu começar agora usando qemu

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

ou

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

Eu tenho a seguinte diferença no comportamento:

com a versão 2 (initramfs externo) tudo funciona bem, "Welcome" é exibido e recebo um aviso. Com a versão 1, no entanto (initramfs incorporado) recebo o aviso

unable to open an initial console

"Bem-vindo" não é exibido e recebo minha solicitação.

Tanto quanto eu entendi o processo, essas duas versões do initramfs devem conter os mesmos arquivos, desde que eu construí-lo (ou ter o kernel construí-lo) a partir de uma pasta idêntica.

Gostaria de saber se alguém pode me ajudar com uma explicação para esse comportamento?

* UPDATE *

como mikeserv disse nos comentários, o kernel inclui um mínimo de initramfs incorporados por padrão. Isto ainda está presente quando se usa um externo, mas é sobrescrito se você incorporar o seu próprio. Descobri que, ao contrário da especificação, isso não é realmente vazio, mas contém uma pasta dev, uma pasta raiz e o dispositivo / dev / console. Este dispositivo é usado ao usar um initramfs externo, mas sobrescrito se você incorporar o seu próprio. Portanto, você precisa incluir o dispositivo / dev / console na sua origem initramfs mknod -m 622 initramfs_src/dev/console c 5 1 ao incorporar seus próprios.

Muito obrigado ao mikeserv, frostschutz e JdeBP por me ajudarem a entender isso!

    
por clw 09.06.2015 / 19:27

2 respostas

2

Eles são realmente idênticos?

O built-in você pode encontrar em /usr/src/linux/usr/initramfs_data.cpio.gz ou extraí-lo da bzImage como descrito aqui: link

Se você usar aquele interno e usá-lo como externo, funcionará?

Se ainda é diferente, o próprio kernel é idêntico? (compare /proc/config.gz para ambos)

Deve haver alguma diferença. Não estou ciente de que o kernel se importa com a origem do initramfs. Eu preferiria que qemu usasse configurações diferentes ao passar o parâmetro -initrd ...

Em um sidenote, seu /init parece com sua infinidade de shells para mim. setsid não é exec . Estou errado?

    
por 09.06.2015 / 19:40
1

Você também pode estar interessado em saber como o Buildroot 2018.02 lida com isso.

Sempre que você usar initramfs ( BR2_TARGET_ROOTFS_INITRAMFS=y ) ou initrd ( BR2_TARGET_ROOTFS_CPIO=n ), ele adicionará o seguinte /init ao seu rootfs link

#!/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 "$@"

A cópia é feita pelo link :

# 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

Também é útil saber que o caminho do init é /init para o initramfs, diferente do /sbin/init caso contrário: O que pode fazer com que a passagem de init = / path / to / program para o kernel não inicie o programa como init?

    
por 16.03.2018 / 13:40