Différence d'exécution d'init avec des initramfs intégrés ou externes?

10

Je construis un système Linux très minimal qui se compose simplement du noyau (v4.1-rc5) et d'un initramfs peuplé de busybox (v1.23.2). Cela fonctionne très bien pour la plupart, mais j'observe une différence dans le comportement de l'exécution des commandes dans / init, que j'utilise un initramfs intégré par rapport à un externe.

Le script / init est:

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

Ensuite, je définis l'option CONFIG_INITRAMFS_SOURCE dans le noyau .config dans le répertoire contenant tous les dossiers pour les initramfs, ou je lance

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

pour le construire.

Lorsque je compile ensuite le noyau, avec ou sans CONFIG_INITRAMFS_SOURCE, je me retrouve avec deux variantes de mon système:

  1. bzImage avec initramfs incorporé

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

quand je commence maintenant ceux qui utilisent qemu

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

ou

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

J'obtiens la différence de comportement suivante:

avec la version 2 (initramfs externes) tout fonctionne bien, "Welcome" s'affiche et je reçois une invite. Avec la version 1 cependant (initramfs intégrés) je reçois l'avertissement

unable to open an initial console

"Bienvenue" ne s'affiche pas et je reçois mon invite.

Pour autant que je comprenne le processus, ces deux versions d'initramfs devraient contenir les mêmes fichiers, puisque je le construis (ou que le noyau le construit) à partir d'un dossier identique.

Je me demande si quelqu'un peut m'aider à expliquer ce comportement?

* METTRE À JOUR *

comme l'a dit mikeserv dans les commentaires, le noyau inclut un initramfs intégré minimal par défaut. Ceci est toujours présent lors de l'utilisation d'un externe, mais est remplacé si vous intégrez le vôtre. J'ai trouvé que contrairement à la spécification, ce n'est en effet pas vide, mais contient un dossier de développement, un dossier racine et le périphérique / dev / console. Cet appareil est ensuite utilisé lors de l'utilisation d'un initramfs externe, mais écrasé si vous intégrez le vôtre. Vous devez donc inclure le périphérique / dev / console dans votre source initramfs mknod -m 622 initramfs_src/dev/console c 5 1lors de l'incorporation de la vôtre.

Merci beaucoup à mikeserv, frostschutz et JdeBP de m'avoir aidé à comprendre cela!

clw
la source
Quelles sont les autorisations définies /dev/consolesur votre intégré? Je pense que la différence pourrait être de savoir qui fait l'emballage dans les deux cas.
mikeserv
Une question similaire est bien sûr stackoverflow.com/questions/10437995 .
JdeBP
@mikeserv, le périphérique de la console a des autorisations et une propriété identiques dans les deux versions.
clw
@JdeBP Je ne suis pas sûr que ce soit similaire, car dans les deux cas, je démarre, je reçois une invite et j'ai une console. Seulement que dans un init exécute l'écho et dans l'autre il ne peut pas.
clw
1
Comment les autorisations auraient-elles pu être les mêmes dans initramfs si vous ne les aviez même pas du tout?
mikeserv

Réponses:

2

Sont-ils vraiment identiques?

Celui intégré, vous pouvez le trouver /usr/src/linux/usr/initramfs_data.cpio.gzou l'extraire du bzImage comme décrit ici: https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging

Si vous utilisez celui intégré et que vous l'utilisez à la place comme externe, cela fonctionne-t-il?

S'il est toujours différent, le noyau lui-même est-il identique? (comparer /proc/config.gzpour les deux)

Il devrait y avoir une différence. Je ne sais pas que le noyau se soucie d'où viennent les initramfs. Je soupçonnerais plus tôt qemud'utiliser des paramètres différents lors du passage du -initrdparamètre ...

Sur un sidenote, votre /initapparence ressemble à ses coquilles infinies qui apparaissent pour moi. setsidne l'est pas exec. Ai-je tort?

frostschutz
la source
1
Cette réponse semble être toutes les questions.
JdeBP
1
@JdeBP: Vous ne pensez pas en quatrième dimension!
frostschutz
1
@frostschutz Merci beaucoup pour votre réponse! Lorsque j'utilise les initramfs que le noyau construit (usr / initramfs_data.cpio.gz) en externe, cela fonctionne aussi très bien! De plus, lorsque je fournis le noyau qui a été compilé avec les initramfs intégrés avec un externe, l'avertissement apparaît, même si l'externe doit remplacer le intégré ( kernel.org/doc/Documentation/filesystems/… ). Donc ce n'est probablement pas non plus qemu -initrd mais quelque chose dans le noyau lui-même. Je n'ai rien changé d'autre que CONFIG_INITRAMFS_SOURCE cependant ..
clw
@frostschutz Répondre à votre On a sidenote, your /init looks like its spawning infinite shells to me. setsid is not exec. Am I wrong?: La boucle imite getty ou des outils similaires, depuis l'appel des shblocs jusqu'à ce que le shell se termine.
stefanjunker
@stefanjunker et ce serait bien, sauf que setsid ne bloque pas du tout ...
frostschutz
1

Vous pouvez également être intéressé par la façon dont Buildroot 2018.02 gère cela.

Chaque fois que vous utilisez initramfs ( BR2_TARGET_ROOTFS_INITRAMFS=y) ou initrd ( BR2_TARGET_ROOTFS_CPIO=n), il ajoute ce qui suit /inità vos 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 copie est effectuée par 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

Il est également utile de savoir que le chemin d'init est /initpour initramfs, contrairement au /sbin/initcontraire: Qu'est - ce qui peut empêcher le passage init = / path / to / program au noyau de ne pas démarrer le programme comme init?

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
la source