カーネル(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つのバリアントが作成されます。
initramfsが埋め込まれたbzImage
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のおかげで、頭を悩ませることができました。
それらは本当に同一ですか?
/usr/src/linux/usr/initramfs_data.cpio.gz
にある組み込みのもの、またはここで説明するようにbzImageから抽出します: https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging
その組み込みのものを使用し、代わりに外部のものとして使用する場合、それは機能しますか?
それでも異なる場合、カーネル自体は同じですか? (両方の/proc/config.gz
を比較してください)
いくつかの違いがあるはずです。カーネルがinitramfsの出所を気にしていることを私は知りません。 -initrd
パラメータを渡すときに、qemu
が異なる設定を使用しているのではないかとすぐに疑うでしょう...
ちなみに、あなたの/init
は、私には無限のシェルを生み出しているように見えます。 setsid
はexec
ではありません。私が間違っている?
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?