主机系统配置

主机系统配置

我目前正在通过实现块设备驱动程序开始内核编程。我能够进行“简单”的实现,并且我想进一步了解块子系统提供的功能。

为此,我想使用 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

然后使用以下命令将其格式化为 ext4mkfs.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 但它没有改变任何东西


更新:
-fda floppy.img作为1ko 的原始归零映像, 精确floppy.img抑制与软盘相关的错误消息,并在启动时节省长达 20 秒的时间。然而,正如您在引导跟踪中看到的那样,/scripts/local-block仍然会运行多次,并且需要最多 10 秒才能进入下一步。


2 - 无法初始化系统


@meuh 评论后更新:

内核似乎无法找到有效的初始化脚本。但是/sbin/init存在于磁盘映像上并且是到 的符号链接/lib/systemd/systemd

我遇到了内核恐慌,但我不知道是什么原因造成的。


问题

我对 qemu 很陌生,我认为我的模拟系统工作已经不远了,但我无法更进一步。

我尝试使用参数,但找不到一种能够完全启动并显示 bash 提示符而不是 initramdisk 提示符的解决方案。

@meuh 评论后更新:
我应该将什么复制到磁盘映像才能初始化系统?

答案1

我还没有这样做,因为通常人们会从 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可能会避免访问软盘。

相关内容