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
私は何を間違ったのですか、それを修正するために何ができますか?
カーネルは、どのdeviceがルートファイルシステムを保持しているかを知らないと言っています。ループマウントは必要ありません。 (続行する前にアンマウントしてください)。
次のようなコマンドを試してください
qemu -kernel bzImage -hda disk.img -append root=/dev/sda
-hda disk.img
パラメーターは、disk.img
に基づいてディスクデバイスをシミュレートするようqemuに指示します。
-append root=/dev/sda
スイッチは、qemuがそのルートデバイスについてカーネルに知らせるために使用されます。これは、カーネルコマンドラインにroot=/dev/sda
を追加することで行われます。 cat /proc/cmdline
を実行すると、これを自分のカーネルのカーネルコマンドラインと比較できます(これは安全です)。 root
パラメータも表示されます。
何が起こっているのかというと、Linuxを「廃止された」方法で起動しようとしているということです。これは、initrd
がramdiskでカーネルによってアンパックされた圧縮cpioアーカイブとは対照的にramdiskであり、古い方法でエンドデバイスに切り替える方法です。
そのモードでは、カーネルはdisk.imgをルートファイルシステムとしてramdiskとしてマウントし、そこで/linuxrc
を実行します。おそらくあなたのケースでは、そのようなファイルはありません。 /linuxrc
(実際のルートファイルシステムのブロックデバイスを起動するために必要なすべてのことを行うことになっています)が終了すると、カーネルは実際のルートファイルシステムをマウントします。
上記のメッセージは、RAMディスクを正常にマウントしていることを示しています(1,0:1はram
のため、/dev/ram0
)。ただし、実際のルートファイルシステム/ dev/sda1(8,1:8はsd
、1はa1
です)。おそらく、カーネルコマンドライン(-append
)を指定しなかったため、その/dev/sda1
は、カーネルのコンパイル時に渡される、またはrdev
を使用してCONFIG_CMDLINEから取得されます。
Disk.imgが、たとえば/sbin/init
...を使用した小さなLinuxディストリビューションのルートファイルシステムを含むことを意図している場合は、おそらく代わりに次のように記述します。
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
は静的にリンクされたバージョンです)そしてそのカーネルでシェルと他のbusyboxユーティリティを取得します)。
このモードでは、カーネルが/init
または/linuxrc
ではなく/sbin/init
を実行することに注意してください。
CONFIG_BLK_DEV_INITRD=y
このカーネル構成オプションも必要です。 Linuxカーネルでのinitrdサポートを有効にします。
Luckly Buildrootは、BR2_TARGET_ROOTFS_CPIO=y
が指定されたときにデフォルトで設定します。
次に、qemu -initrd
オプションを使用してCPIOをQEMUに渡します。私の完全な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