web-dev-qa-db-ja.com

組み込みのinitramfsと外部のinitramfsを使用したinitの実行の違いは?

カーネル(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)では、すべてが正常に機能し、「ようこそ」が表示され、プロンプトが表示されます。ただし、バージョン1(埋め込みinitramfs)では、警告が表示されます

unable to open an initial console

「ようこそ」が表示されず、プロンプトが表示されます。

私がプロセスを理解している限り、これら2つのバージョンのinitramfsには同じファイルが含まれているはずです。これは、同じフォルダーからビルドする(またはカーネルにビルドさせる)ためです。

誰かがこの振る舞いの説明を手伝ってくれるのだろうか?

*更新*

mikeservがコメントで述べたように、カーネルにはデフォルトごとに最小限の組み込みinitramfsが含まれています。これは外部のものを使用する場合でも存在しますが、独自のものを埋め込むと上書きされます。仕様に反して、これは実際には空ではありませんが、devフォルダー、ルートフォルダー、および/ dev/consoleデバイスが含まれていることがわかりました。このデバイスは、外部initramfsを使用するときに使用されますが、独自のデバイスを埋め込むと上書きされます。したがって、/ dev/consoleデバイスをinitramfsソースに含める必要がありますmknod -m 622 initramfs_src/dev/console c 5 1自分で埋め込む場合。

Mikeserv、frostschutz、JdeBPのおかげで、頭を悩ませることができました。

10
clw

それらは本当に同一ですか?

/usr/src/linux/usr/initramfs_data.cpio.gzにある組み込みのもの、またはここで説明するようにbzImageから抽出します: https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging

その組み込みのものを使用し、代わりに外部のものとして使用する場合、それは機能しますか?

それでも異なる場合、カーネル自体は同じですか? (両方の/proc/config.gzを比較してください)

いくつかの違いがあるはずです。カーネルがinitramfsの出所を気にしていることを私は知りません。 -initrdパラメータを渡すときに、qemuが異なる設定を使用しているのではないかとすぐに疑うでしょう...

ちなみに、あなたの/initは、私には無限のシェルを生み出しているように見えます。 setsidexecではありません。私が間違っている?

2
frostschutz

Buildroot2018.02がこれをどのように処理するかにも興味があるかもしれません。

Initramfs(BR2_TARGET_ROOTFS_INITRAMFS=y)またはinitrd(BR2_TARGET_ROOTFS_CPIO=n)を使用すると、rootfsに次の/initが追加されます 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とは異なり、initramfsのinitパスが/sbin/initであることを知っておくと便利です。 init =/path/to/programをカーネルに渡してもプログラムが起動しない理由init?