
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
私が何を間違っているのか、それを解決するにはどうすればよいですか?
答え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/sda
qemuはこのスイッチを使用してカーネルにルートデバイスを通知します。これはカーネルコマンドラインに追加することによって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