Я создаю очень минимальную систему Linux, которая состоит из ядра (v4.1-rc5) и initramfs, заполненных busybox (v1.23.2). По большей части он работает нормально, но я наблюдаю разницу в поведении выполнения команд в / init, использую ли я встроенный initramfs по сравнению с внешним.
Сценарий / 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
Затем я либо устанавливаю параметр CONFIG_INITRAMFS_SOURCE в ядре .config в каталог, содержащий все папки для initramfs, либо запускаю
find . | cpio -H newc -o | gzip > ../rootfs.cpio.gz
построить это.
Когда я затем скомпилирую ядро с набором CONFIG_INITRAMFS_SOURCE или без него, я получаю два варианта моей системы:
bzImage со встроенными initramfs
bzImage + rootfs.cpio.gz (внешний initramfs)
когда я сейчас начинаю тех, кто использует qemu
qemu-system-x86_64 -enable-kvm -kernel bzImage
или
qemu-system-x86_64 -enable-kvm -kernel bzImage -initrd rootfs.cpio.gz
Я получаю следующую разницу в поведении:
с версией 2 (внешние initramfs) все работает нормально, отображается «Добро пожаловать», и я получаю подсказку. Однако с версией 1 (встроенные initramfs) я получаю предупреждение
unable to open an initial console
«Добро пожаловать» не отображается, и я получаю подсказку.
Насколько я понимаю, эти две версии initramfs должны содержать одинаковые файлы, так как я собираю их (или собираю ядро) из одинаковой папки.
Интересно, кто-нибудь может мне помочь с объяснением этого поведения?
* ОБНОВИТЬ *
Как сказал в комментариях mikeserv, ядро включает минимальное количество встроенных initramfs по умолчанию. Это все еще присутствует при использовании внешнего, но перезаписывается, если вы вставляете свой собственный. Я обнаружил, что вопреки спецификации, он действительно не пустой, но содержит папку dev, корневую папку и устройство / dev / console. Это устройство затем используется при использовании внешних initramfs, но перезаписывается, если вы встраиваете свое собственное. Поэтому вы должны включить устройство / dev / console в исходный код initramfs mknod -m 622 initramfs_src/dev/console c 5 1
при встраивании своего собственного.
Большое спасибо mikeserv, frostschutz и JdeBP за помощь в этом!
/dev/console
на вашем встроенном? Я думаю, что разница может заключаться в том, кто делает упаковку в двух случаях.Ответы:
Они действительно идентичны?
Встроенный, который вы можете найти
/usr/src/linux/usr/initramfs_data.cpio.gz
или извлечь из bzImage, как описано здесь: https://wiki.gentoo.org/wiki/Custom_Initramfs#SalvagingЕсли вы используете этот встроенный и вместо этого используете его как внешний, он работает?
Если он все еще другой, само ядро идентично? (сравните
/proc/config.gz
для обоих)Должна быть какая-то разница. Я не знаю, что ядру важно, откуда взялись initramfs. Я бы скорее заподозрил
qemu
использование разных настроек при передаче-initrd
параметра ...С одной стороны,
/init
для меня ты выглядишь как бесконечный снаряд.setsid
неexec
. Я ошибся?источник
On a sidenote, your /init looks like its spawning infinite shells to me. setsid is not exec. Am I wrong?
: цикл имитирует getty или подобные инструменты, так как вызовsh
блоков до выхода из этой оболочки.Вы также можете быть заинтересованы в том, как Buildroot 2018.02 справляется с этим.
Всякий раз, когда вы используете initramfs (
BR2_TARGET_ROOTFS_INITRAMFS=y
) или initrd (BR2_TARGET_ROOTFS_CPIO=n
), он добавляет следующее/init
в ваши rootfs https://github.com/buildroot/buildroot/blob/2018.02/fs/cpio/initКопия сделана https://github.com/buildroot/buildroot/blob/2018.02/fs/cpio/cpio.mk :
Также полезно знать, что путь инициализации предназначен
/init
для initramfs, в отличие от/sbin/init
других: что может заставить передачу init = / path / to / program в ядро не запускать программу как init?источник