初期化を実行するための組み込みinitramfsと外部initramfsの違いは何ですか?

初期化を実行するための組み込みinitramfsと外部initramfsの違いは何ですか?

私はカーネル(v4.1-rc5)とbusybox(v1.23.2)で満たされたinitramfsで構成された非常に小さなLinuxシステムを構築しています。ほとんどの場合、うまく動作しますが、組み込みのinitramfsを使用するか外部initramfsを使用するか、/ initのコマンド実行が異なる動作をすることが観察されました。

/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

次に、kernel.configのCONFIG_INITRAMFS_SOURCEオプションをinitramfsのすべてのフォルダを含むディレクトリに設定するか、次を実行します。

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

それを構築します。

その後、カーネルをコンパイルすると、CONFIG_INITRAMFS_SOURCEが設定されているかどうかにかかわらず、システムの2つのバリエーションが生成されます。

  1. initramfsに含まれるbzImage

  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(embedded initramfs)の場合は警告が表示されます。

unable to open an initial console

「ようこそ」は表示されませんが、メッセージが表示されます。

プロセスについて私が理解したように、initramfsの両方のバージョンが同じフォルダにビルドされたので(またはカーネルがビルドするようにしたため)、同じファイルを含める必要があります。

この動作を説明するのに役立つ人がいるかどうか疑問に思います。

*更新*

mikeservがコメントで述べたように、カーネルには基本的に最小限の組み込みinitramfsが含まれています。外部アイテムを使用している場合はまだ存在しますが、自分のアイテムを含めると上書きされます。私は標準とは異なり、これは実際には空ではなく、devフォルダ、ルートフォルダ、および/dev/consoleデバイスが含まれていることを発見しました。その後、このデバイスは外部initramfsを使用するときに使用されますが、直接挿入するとオーバーライドされます。したがって、mknod -m 622 initramfs_src/dev/console c 5 1自分のデバイスを組み込むときは、initramfsソースに/ dev / consoleデバイスを含める必要があります。

この問題を解決するのに役立つmikeserv、Frostschutz、JdeBPに感謝します!

答え1

本当に同じですか?

/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。私は間違っていますか?

答え2

Buildroot 2018.02でこの問題を処理する方法に興味があるかもしれません。

BR2_TARGET_ROOTFS_INITRAMFS=yinitramfs( ) または initrd( ) を使用するたびに、rootfs にBR2_TARGET_ROOTFS_CPIO=n以下が追加されます。/inithttps://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

他の場合とは異なり、initramfsの初期化パスを知ることも/init便利です。/sbin/initinitのようなプログラムを起動するのではなく、init = / path / to / programがカーネルに渡されるのはなぜですか?

関連情報