Відмінність виконання init із вбудованими та зовнішніми initramfs?


10

Я будую дуже мінімальну систему Linux, яка просто складається з ядра (v4.1-rc5) та initramfs, заселеного busbox (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 або без нього, я закінчую два варіанти моєї системи:

  1. bzImage із вбудованими initramfs

  2. 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) все працює нормально, відображається "Welcome", і я отримую підказку. Однак у версії 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на вбудованому? Я думаю, що різниця може полягати в тому, хто робить упаковку в двох випадках.
mikeserv

Подібне питання, звичайно, є stackoverflow.com/questions/10437995 .
JdeBP

@mikeserv консольний пристрій має однакові дозволи та права власності в обох складах.
clw

@JdeBP Я не впевнений, чи схожий він, оскільки в обох випадках я завантажуюся, отримую підказку та консольний пристрій. Тільки те, що в одному init виконує відлуння, а в іншому він не може.
clw

1
Яким чином дозволи могли бути однаковими в initramfs, якщо ви навіть не мали цього?
mikeserv

Відповіді:


2

Вони справді однакові?

Вбудований ви можете знайти /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. Я помиляюся?


1
Ця відповідь, здається, є на всі питання.
JdeBP

1
@JdeBP: Ти не думаєш четвертомірне!
frostschutz

1
@frostschutz Дякую за вашу відповідь! Коли я використовую initramfs, які будує ядро ​​(usr / initramfs_data.cpio.gz), як зовнішній, він також добре працює! Крім того, коли я постачаю ядро, яке було складено із вбудованими initramfs із зовнішнім, з’являється попередження, навіть якщо зовнішнє має перезаписати вбудований ( kernel.org/doc/Documentation/filesystems/… ). Тож його, ймовірно, також не qemu -initrd, а щось у самому ядрі. Я нічого іншого не змінив, ніж CONFIG_INITRAMFS_SOURCE, хоча ..
clw

@frostschutz Відповідь на ваше On a sidenote, your /init looks like its spawning infinite shells to me. setsid is not exec. Am I wrong?: цикл імітує getty чи подібні інструменти, оскільки виклик shблокується до тих пір, поки не закінчується оболонка.
stefanjunker

@stefanjunker, і це було б добре, хіба setid взагалі не блокує ...
frostschutz

1

Можливо, вам також буде цікаво, як 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

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

Копія робиться 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

Корисно також знати, що шлях init призначений /initдля initramfs, на відміну від /sbin/initіншого: Що може зробити перехід init = / path / to / program до ядра не запускати програму як init?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.