我目前正在通过实现块设备驱动程序开始内核编程。我能够进行“简单”的实现,并且我想进一步了解块子系统提供的功能。
为此,我想使用 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.img
的floppy.img
原始归零图像可以抑制软盘相关的错误消息,并在启动时最多节省 20 秒。但是,正如您在引导跟踪中看到的那样,/scripts/local-block
它仍然会运行几次,并且在传递到下一步之前最多需要 10 秒。
2 - 无法初始化系统
@meuh 评论后更新:
内核似乎无法找到有效的初始化脚本。但是/sbin/init
,它存在于磁盘映像上,并且是指向/lib/systemd/systemd
.
我正在经历内核恐慌,但我不知道是什么原因造成的。
问题
我对 qemu 很陌生,我认为我离让我的模拟系统工作不远了,但我无法走得更远。
我尝试使用参数,但找不到能够完全启动并使用 bash 提示而不是 initramdisk 提示的解决方案。
@meuh 评论后更新:
我应该将什么复制到磁盘映像才能初始化系统?
我没有这样做,因为通常人们会从 iso 或现有的 qemu 映像安装 qemu,所以可能有比以下更简单的方法。您缺少的几乎等同于chroot所需的文件系统。
要尝试的一件事是
它下降并解压缩大约 300Mbytes 的文件,您可以将其“启动”为 systemd 容器并使用它进行测试
见
man machinectl
。您可以通过将 qemu 映像设置为块设备来挂载它:并将这棵树复制到其中。运行 qemu 时,您通常需要提供更大的 VM 大小以避免崩溃:
使用
-boot d
可能会避免访问软盘。