Różnica w wykonaniu init z osadzonymi vs. zewnętrznymi initramfs?


10

Buduję bardzo minimalny system Linux, który po prostu składa się z jądra (v4.1-rc5) i initramfs wypełnionego busybox (v1.23.2). W większości działa dobrze, ale obserwuję różnicę w zachowaniu wykonywania poleceń w / init, czy używam osadzonego initramfs vs. zewnętrznego.

Skrypt / init to:

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

Następnie ustawiam opcję CONFIG_INITRAMFS_SOURCE w jądrze .config na katalog zawierający wszystkie foldery dla initramfs lub uruchamiam

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

zbudować to.

Kiedy kompiluję jądro, z zestawem CONFIG_INITRAMFS_SOURCE lub bez niego, kończę na dwóch wariantach mojego systemu:

  1. bzImage z osadzonymi initramfs

  2. bzImage + rootfs.cpio.gz (zewnętrzne initramfs)

kiedy teraz zacznę używać qemu

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

lub

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

Dostaję następującą różnicę w zachowaniu:

w wersji 2 (zewnętrzne initramfs) wszystko działa dobrze, wyświetla się „Welcome” i pojawia się monit. Jednak w wersji 1 (osadzone initramfs) pojawia się ostrzeżenie

unable to open an initial console

„Witamy” nie jest wyświetlane i pojawia się monit.

O ile rozumiem ten proces, te dwie wersje initramfs powinny zawierać te same pliki, ponieważ tworzę je (lub mam jądro) z identycznego folderu.

Zastanawiam się, czy ktoś może mi pomóc w wyjaśnieniu tego zachowania?

* AKTUALIZACJA *

jak powiedział mikeserv w komentarzach, jądro zawiera domyślnie minimalną liczbę osadzonych initramfs. Jest to nadal obecne, gdy używasz zewnętrznego, ale zostanie zastąpione, jeśli umieścisz własne. Odkryłem, że wbrew specyfikacji, to nie jest rzeczywiście puste, ale zawiera folder dev, folder główny i urządzenie / dev / console. To urządzenie przyzwyczaja się wtedy, gdy używasz zewnętrznego initramfs, ale jest zastępowane, jeśli osadzasz własne. Musisz więc umieścić urządzenie / dev / console w źródle initramfs mknod -m 622 initramfs_src/dev/console c 5 1podczas osadzania własnego.

Wielkie dzięki dla mikeserv, frostschutz i JdeBP za pomoc w zrozumieniu tego!


Jakie uprawnienia są ustawione /dev/consolena Twoim wbudowanym? Myślę, że różnica może dotyczyć tego, kto zajmuje się pakowaniem w obu przypadkach.
mikeserv

Podobnym pytaniem jest oczywiście stackoverflow.com/questions/10437995 .
JdeBP,

@mikeserv urządzenie konsoli ma identyczne uprawnienia i własność w obu kompilacjach.
clw

@JdeBP Nie jestem pewien, czy jest tak podobny, ponieważ w obu przypadkach uruchamiam się, otrzymuję monit i mam urządzenie konsoli. Tyle tylko, że w jednym init wykonuje echo, aw drugim nie.
clw

1
Jak uprawnienia mogą być takie same w initramfs, jeśli w ogóle ich nie masz?
mikeserv

Odpowiedzi:


2

Czy są naprawdę identyczne?

Wbudowany można go znaleźć /usr/src/linux/usr/initramfs_data.cpio.gzlub wyodrębnić z bzImage, jak opisano tutaj: https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging

Jeśli użyjesz tego wbudowanego i użyjesz go jako zewnętrznego, czy to działa?

Jeśli nadal jest inaczej, czy samo jądro jest identyczne? (porównaj /proc/config.gzdla obu)

Powinna być jakaś różnica. Nie wiem, czy jądro dba o to, skąd pochodzi initramfs. Wcześniej podejrzewam, że qemuużywam różnych ustawień podczas przekazywania -initrdparametru ...

Na marginesie, /initwygląda mi na to, że spawnuje nieskończone pociski. setsidnie jest exec. Czy się mylę?


1
Ta odpowiedź wydaje się zawierać wszystkie pytania.
JdeBP,

1
@JdeBP: Nie myślisz w czwartym wymiarze!
frostschutz

1
@frostschutz Bardzo dziękuję za odpowiedź! Kiedy używam initramfs budowanego przez jądro (usr / initramfs_data.cpio.gz) jako zewnętrznego, działa również dobrze! Ponadto, gdy dostarczę jądro, które zostało skompilowane z osadzonymi initramfs z zewnętrznym, pojawia się ostrzeżenie, nawet jeśli zewnętrzny powinien nadpisać osadzony ( kernel.org/doc/Documentation/filesystems/… ). Więc prawdopodobnie nie jest to również qemu -initrd, ale coś w samym jądrze. Nie zmieniłem jednak nic innego niż CONFIG_INITRAMFS_SOURCE ..
clw

@frostschutz Odpowiadając na On a sidenote, your /init looks like its spawning infinite shells to me. setsid is not exec. Am I wrong?: Pętla naśladuje getty lub podobne narzędzia, ponieważ wywołują shbloki, dopóki ta powłoka nie wyjdzie.
stefanjunker

@stefanjunker i to by było w porządku, ale setid wcale nie blokuje ...
frostschutz

1

Możesz być także zainteresowany tym, jak radzi sobie z tym Buildroot 2018.02.

Ilekroć używasz initramfs ( BR2_TARGET_ROOTFS_INITRAMFS=y) lub initrd ( BR2_TARGET_ROOTFS_CPIO=n), dodaje następujące elementy /initdo twoich rootfów 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 "$@"

Kopia jest wykonywana przez 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

Warto również wiedzieć, że ścieżka inicjująca jest /initprzeznaczona dla initramfs, w przeciwieństwie do /sbin/initinnych: Co może sprawić, że przekazanie init = / ścieżka / do / programu do jądra nie uruchomi programu jako init?

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.