Linux

Qemu - 模擬自己的系統來測試核心模組

  • April 16, 2018

我目前正在通過實現塊設備驅動程序開始核心程式。我能夠進行“簡單”的實現,並且我想進一步了解塊子系統提供的功能。

為此,我想使用 qemu 模擬我自己的作業系統,以避免每次我在核心設備程式碼中出錯時使我的開發作業系統崩潰。

主機系統配置

在我的工作站上,我使用的是執行核心 4.9.0 的 Debian 9。

$ uname -a
Linux PC325 4.9.0-6-amd64 #1 SMP Debian 4.9.82-1+deb9u3 (2018-03-02) x86_64 GNU/Linux

鏡像磁碟創建

為了創建虛擬機,我創建了一個 500M 的原始圖像dd if=/dev/zero of=vm-image.raw bs=1M count=512

然後將其格式化為 ext4 使用mkfs.ext4 vm-image.raw


@meuh 評論後更新:

然後我填充了磁碟映像,如下所示:

mount vm-image.raw /mnt
mkdir /mnt/dev /mnt/lib /mnt/proc /mnt/root /mnt/run /mnt/sbin /mnt/sys
cp -r /etc /mnt/
cp -r /lib/systemd /mnt/lib
ln -s /lib/systemd/systemd /mnt/sbin/init

我現在正在嘗試啟動模擬作業系統,但在配置它時遇到了一些問題。

執行命令

$ qemu-system-x86_64 -k fr -kernel /boot/vmlinuz-$(uname -r) -initrd /boot/initrd.img-$(uname -r) -hda vm/vm-image.raw -append "initrd=/boot/initrd.img-$(uname -r) root=/dev/sda rw console=ttyS0" -nographic

引導跟踪

[...] Kernel boot sequence [...]

Begin: Loading essential drivers ... done.
Begin: Running /scripts/init-premount ... done.
Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done.
Begin: Running /scripts/local-premount ... [    2.015241] tsc: Refined TSC clocksource calibration: 3392.292 MHz
[    2.016768] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x30e5dd94d34, max_idle_ns: 440795304975 ns
[    2.895630] random: fast init done
Begin: Waiting for suspend/resume device ... Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
[   11.111765] random: crng init done
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
done.
Gave up waiting for suspend/resume device
done.
Begin: Will now check root file system ... fsck from util-linux 2.29.2
[/sbin/fsck.ext4 (1) -- /dev/sda] fsck.ext4 -a -C0 /dev/sda 
/dev/sda: clean, 3607/32768 files, 12617/131072 blocks
done.
[   35.528453] EXT4-fs (sda): mounted filesystem with ordered data mode. Opts: (null)
done.
Begin: Running /scripts/local-bottom ... done.
Begin: Running /scripts/init-bottom ... done.
run-init: /sbin/init: No such file or directory
[   35.569247] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100
[   35.569247] 
[   35.570469] CPU: 0 PID: 1 Comm: run-init Not tainted 4.9.0-6-amd64 #1 Debian 4.9.82-1+deb9u3
[   35.571599] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
[   35.572695]  0000000000000000 ffffffff9792e074 ffff974c05e14d00 ffffa66e8003feb8
[   35.573741]  ffffffff9777cfbd ffff974c00000010 ffffa66e8003fec8 ffffa66e8003fe60
[   35.574780]  a4112d94e56af84a ffff974c05e14d80 0000000000000100 ffff974c05e84490
[   35.575793] Call Trace:
[   35.576132]  [<ffffffff9792e074>] ? dump_stack+0x5c/0x78
[   35.576815]  [<ffffffff9777cfbd>] ? panic+0xe4/0x23f
[   35.577453]  [<ffffffff9767c2de>] ? do_exit+0xade/0xae0
[   35.578136]  [<ffffffff978058b4>] ? vfs_write+0x144/0x190
[   35.578830]  [<ffffffff9767c313>] ? SyS_exit+0x13/0x20
[   35.579510]  [<ffffffff97603b7f>] ? do_syscall_64+0x8f/0xf0
[   35.580223]  [<ffffffff97c113b8>] ? entry_SYSCALL_64_after_swapgs+0x42/0xb0
[   35.581209] Kernel Offset: 0x16600000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[   35.582584] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100
[   35.582584] 

問題

1 - 試圖讀取磁片設備

在啟動時,核心似乎試圖從不存在或不可讀的磁片設備中讀取。核心在 30 次嘗試後放棄了,所以這不是一個關鍵問題,但它會使引導序列減慢 30 秒。

我嘗試使用-no-fd-bootchk選項執行 qemu,但它沒有改變任何東西


更新:
精確地作為 1ko-fda floppy.imgfloppy.img原始歸零圖像可以抑制磁片相關的錯誤消息,並在啟動時最多節省 20 秒。但是,正如您在引導跟踪中看到的那樣,/scripts/local-block它仍然會執行幾次,並且在傳遞到下一步之前最多需要 10 秒。


2 - 無法初始化系統


@meuh 評論後更新:

核心似乎無法找到有效的初始化腳本。但是/sbin/init,它存在於磁碟映像上,並且是指向/lib/systemd/systemd.

我正在經歷核心恐慌,但我不知道是什麼原因造成的。


問題

我對 qemu 很陌生,我認為我離讓我的模擬系統工作不遠了,但我無法走得更遠。

我嘗試使用參數,但找不到能夠完全啟動並使用 bash 提示而不是 initramdisk 提示的解決方案。

@meuh 評論後更新:

我應該將什麼複製到磁碟映像才能初始化系統?

我沒有這樣做,因為通常人們會從 iso 或現有的 qemu 映像安裝 qemu,所以可能有比以下更簡單的方法。您缺少的幾乎等同於chroot所需的文件系統。

要嘗試的一件事是

sudo debootstrap --arch=amd64 unstable ~/debian-tree/

它下降並解壓縮大約 300Mbytes 的文件,您可以將其“啟動”為 systemd 容器並使用它進行測試

sudo systemd-nspawn -D ~/debian-tree/ -b

man machinectl。您可以通過將 qemu 映像設置為塊設備來掛載它:

sudo apt-get install qemu-utils
sudo modprobe nbd
ls /dev/nbd*   # gives /dev/nbd0  /dev/nbd1 ...
sudo qemu-nbd -c /dev/nbd0 /my/vm-image
sudo mount /dev/nbd0 /mnt/...  # nbd0p1 if you have partitioned
sudo rsync -HSaxX ~/debian-tree/ /mnt/... 

並將這棵樹複製到其中。執行 qemu 時,您通常需要提供更大的 VM 大小以避免崩潰:

qemu-system-x86_64 -m 512M ... -machine pc,accel=kvm  -cpu host -enable-kvm

使用-boot d可能會避免訪問磁片。

引用自:https://unix.stackexchange.com/questions/438101