Linuxカーネルがinitrdを正しく見つけることができません。

Linuxカーネルがinitrdを正しく見つけることができません。

Linuxカーネルをコンパイルし、それをQEMUでデバッグしたいと思います。コマンドを実行して起動用ファイルを作成しました。

$ qemu-img create -f raw disk.img 200M
$ mkfs.ext2 -F disk.img
# mkdir /mnt/rootfs
# mount -o loop disk.img /mnt/rootfs

それから私はqemu -kernel bzImage -initrd disk.img次のような画面を得ました:

Kernel panic - not syncing: VFS: unable to mount root fs on unknown block

私のQEMU画面

私が何を間違っているのか、それを解決するにはどうすればよいですか?

答え1

何が起こっているのかは、「古い」方法でLinuxを起動しようとしているということです。これはinitrd、カーネルによってramfsから解凍され、以前の方法を使用してターミナルデバイスに切り替える圧縮cpioアーカイブではなく、RAMディスクです。

このモードでは、カーネルはdisk.imgをルートファイルシステムにRAMディスクとしてマウントし、そこで/linuxrc実行します。あなたの場合、そのようなファイルがない可能性があります。/linuxrc(実際のルートファイルシステムのブロックデバイスを起動するために必要なすべての作業を実行する必要があります)が終了すると、カーネルは実際のルートファイルシステムをマウントします。

上記のメッセージはRAMディスク(1,0:1はを表します)を正常にマウントしましたが、ram実際の/dev/ram0ルートファイルシステムである/ dev / sda1(8,1:8はを表しsd、1はを表しますa1)をマウントしませんでした。を示します。おそらく、カーネルコマンドライン(-append)を指定していないので、/dev/sda1カーネルをコンパイルしたりrdev

disk.imgに小規模なLinuxディストリビューションなどのルートファイルシステムを含める場合は、代わり/sbin/initに作成できます。

kvm -kernel kernel.img -initrd disk.img -append 'root=/dev/ram0`

これにより、カーネルはRAMディスクを実際のルートファイルシステムとして扱います(pivot_root他のファイルシステムを使用することもできます)。

カーネルメッセージを見やすくするには、シリアル出力を使用することをお勧めします。

kvm -kernel kernel.img -initrd disk.img -nographic -append "root=/dev/ram0 console=ttyS0"

あるいは、init ramdiskの代わりにinit ramfsを使用することもできます。

mkdir -p RAMFS/{bin,dev} 
cd RAMFS/bin
cp /bin/busybox .
"$PWD/busybox" --install .
cd ..
cp -a /dev/{null,tty,zero,console} dev
printf '%s\n' "#! /bin/sh -" "exec /bin/sh" > init
chmod +x init
find . | cpio -oHnewc | gzip > ../initramfs.gz
cd ..
kvm -kernel kernel.img -initrd initramfs.gz

(静的にリンクされたバージョンが提供されていますbusybox。)このカーネルからシェルやその他のビジボックスユーティリティを入手できます。

カーネルはこのモード/initとは対照的に動作します/linuxrc/sbin/init

答え2

カーネルは何が何であるかわからないと言います。装備ルートファイルシステムを保存します。インストールループは必要ありません。 (続行する前に削除してください)。

次のコマンドを試してください。

qemu -kernel bzImage -hda disk.img -append root=/dev/sda

この-hda disk.imgパラメータはqemuにdisk.img

-append root=/dev/sdaqemuはこのスイッチを使用してカーネルにルートデバイスを通知します。これはカーネルコマンドラインに追加することによってroot=/dev/sda行われます。次のようにして、それを自分のカーネルカーネルコマンドラインcat /proc/cmdline(安全)と比較できます。また、そこにパラメータがあることも確認する必要がありますroot

答え3

CONFIG_BLK_DEV_INITRD=y

このカーネル構成オプションも必要です。 Linuxカーネルでinitrdサポートを有効にします。

BR2_TARGET_ROOTFS_CPIO=y幸いなことに、Buildrootは指定された場合はデフォルトでこれを設定します。

その後、このオプションを使用してCPIOをQEMUに渡すことができますqemu -initrd。私の完全なQEMUコマンドは次のとおりです。

./buildroot/output.x86_64~/host/usr/bin/qemu-system-x86_64 -m 128M -monitor telnet::45454,server,nowait -netdev user,hostfwd=tcp::45455-:45455,id=net0 -smp 1  -M pc -append ' nopat nokaslr norandmaps printk.devkmsg=on printk.time=y console=ttyS0' -device edu -device lkmc_pci_min -device virtio-net-pci,netdev=net0 -kernel ./buildroot/output.x86_64~/images/bzImage  -nographic  -initrd './buildroot/output.x86_64~/images/rootfs.cpio'

以下は、シンプルで完全に自動化されたBuildroot + QEMUの例です。https://github.com/cirosantilli/linux-kernel-module-cheat/tree/b3868a3b009f2ab44fa6d3db3d174930b3cf7b69#initrd

関連情報