如何将磁盘映像附加到包含 linux 内核的根文件系统的 QEMU?
How to attach a disk image to QEMU containing root filesystem for linux kernel?
我可以使用 -kernel
在 QEMU 上启动 linux 内核,这非常简单明了。
但现在我正在尝试不同的东西。我模拟的是UEFI+GRUB+Kernel的组合
我已经从源代码构建了 OVMF 和 GRUB2,也能够加载内核映像,但是在创建 rootfs 磁盘映像并将其附加到 qemu 以便内核检测到它时遇到困难。
这就是我为内核准备 rootfs.img 的方式:
#Create an empty ext2 disk image of size 10M
dd if=/dev/zero of=rootfs.img bs=1M count=10
mke2fs -j rootfs.img
#Populate the disk
mkdir /mnt/rootfs
mount -o loop rootfs.img /mnt/rootfs
rsync -a busybox/_install/ /mnt/rootfs
chown -R root:root /mnt/rootfs
sync
umount /mnt/rootfs
这是我的 GRUB 配置的样子:
menuentry "Linux Kernel Boot" {
set root=(hd0,msdos1)
linux (hd0,msdos1)/bzImage-x86_64 root=/dev/sdb1 rootwait console=ttyS0,115200n8 console=tty0
}
这是我用来启动 qemu 的命令:
qemu-system-x86_64 -m 2G -drive if=pflash,format=raw,readonly,file=OVMF_CODE.fd -drive if=pflash,format=raw,file=OVMF_VARS.fd -net none -serial stdio -display none -hda fat:disk -drive file=rootfs.img,index=1
我附加为 hda
的 FAT 磁盘包含我的 GRUB 和内核映像。我想要一个单独的磁盘用于 rootfs,并且不想为此目的使用此 FAT。
安装程序引导至内核,但内核无法挂载磁盘 sdb1
,因此在 rootfs 中看不到 init
,因此出现内核崩溃。以下是内核日志:
[ 1.030290] NET: Registered protocol family 17
[ 1.033540] ata1.01: configured for MWDMA2
[ 1.042119] Key type dns_resolver registered
[ 1.045150] scsi 0:0:0:0: Direct-Access ATA QEMU HARDDISK 2.5+ PQ: 0 ANSI: 5
[ 1.049509] sched_clock: Marking stable (1049235510, 0)->(1378961625, -329726115)
[ 1.058429] registered taskstats version 1
[ 1.060917] Loading compiled-in X.509 certificates
[ 1.066242] sd 0:0:0:0: [sda] 1032192 512-byte logical blocks: (528 MB/504 MiB)
[ 1.070386] sd 0:0:0:0: Attached scsi generic sg0 type 0
[ 1.074945] sd 0:0:0:0: [sda] Write Protect is off
[ 1.079585] scsi 0:0:1:0: Direct-Access ATA QEMU HARDDISK 2.5+ PQ: 0 ANSI: 5
[ 1.082483] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 1.090820] Magic number: 0:346:692
[ 1.094970] sd 0:0:1:0: [sdb] 20480 512-byte logical blocks: (10.5 MB/10.0 MiB)
[ 1.097740] sd 0:0:1:0: [sdb] Write Protect is off
[ 1.101097] sd 0:0:1:0: Attached scsi generic sg1 type 0
[ 1.108436] console [netcon0] enabled
[ 1.110947] netconsole: network logging started
[ 1.114830] sd 0:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 1.122345] scsi 1:0:0:0: CD-ROM QEMU QEMU DVD-ROM 2.5+ PQ: 0 ANSI: 5
[ 1.138010] sda: sda1
[ 1.142638] sr 1:0:0:0: [sr0] scsi3-mmc drive: 4x/4x cd/rw xa/form2 tray
[ 1.145513] cdrom: Uniform CD-ROM driver Revision: 3.20
[ 1.149749] cfg80211: Loading compiled-in X.509 certificates for regulatory database
[ 1.164130] sd 0:0:1:0: [sdb] Attached SCSI disk
[ 1.169575] sr 1:0:0:0: Attached scsi generic sg2 type 5
[ 1.174262] sd 0:0:0:0: [sda] Attached SCSI disk
[ 1.190198] cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
[ 1.194508] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
[ 1.197606] cfg80211: failed to load regulatory.db
[ 1.200837] ALSA device list:
[ 1.203626] No soundcards found.
[ 1.531285] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input3
[ 1.537979] md: Waiting for all devices to be available before autodetect
[ 1.541357] md: If you don't use raid, use raid=noautodetect
[ 1.548186] md: Autodetecting RAID arrays.
[ 1.551815] md: autorun ...
[ 1.554889] md: ... autorun DONE.
[ 1.559995] VFS: Cannot open root device "sdb1" or unknown-block(8,17): error -6
[ 1.563196] Please append a correct "root=" boot option; here are the available partitions:
[ 1.566295] 0800 516096 sda
[ 1.566326] driver: sd
[ 1.572371] 0801 516064 sda1 be1afdfa-01
[ 1.572397]
[ 1.577560] 0810 10240 sdb
[ 1.577573] driver: sd
[ 1.582573] 0b00 1048575 sr0
[ 1.582585] driver: sr
[ 1.587948] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,17)
[ 1.590831] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.15.3+ #2
[ 1.593384] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 0.0.0 02/06/2015
[ 1.596327] Call Trace:
[ 1.600043] dump_stack+0x46/0x59
[ 1.602665] panic+0xca/0x218
[ 1.604991] ? printk+0x3e/0x46
[ 1.607197] mount_block_root+0x174/0x223
[ 1.609463] ? set_debug_rodata+0xc/0xc
[ 1.611851] mount_root+0xfb/0x104
[ 1.614159] prepare_namespace+0x130/0x166
[ 1.616415] kernel_init_freeable+0x1c5/0x1d7
[ 1.618676] ? rest_init+0xb0/0xb0
[ 1.621326] kernel_init+0x5/0xf0
[ 1.623768] ret_from_fork+0x35/0x40
[ 1.627035] Kernel Offset: 0x24800000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[ 1.632240] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,17)
有人可以指导在 qemu 中附加磁盘的正确方法来解决这个问题,或者我是否需要更改 GRUB 配置中的某些内容?
编辑
这次我按照@stark 的建议创建了分区table 的磁盘镜像
$ dd if=/dev/zero of=rootfs.img bs=1M count=10
#Using fdisk, created a partition of type Linux (83). This is how it looks now
$ fdisk -l rootfs.img
Disk rootfs.img: 10 MiB, 10485760 bytes, 20480 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xc08ab9b0
Device Boot Start End Sectors Size Id Type
rootfs.img1 2048 20479 18432 9M 83 Linux
$ sudo losetup -o 1048576 --sizelimit 10485248 /dev/loop23 rootfs.img
$ sudo mkfs.ext2 /dev/loop23
$ sudo mount /dev/loop23 /mnt/rootfs
$ sudo cp -vrf busybox/_install/* /mnt/rootfs/
$ sudo umount /mnt/rootfs
$ sudo losetup -d /dev/loop23
现在我再次使用与上面相同的命令启动内核,但这次内核只是挂起:
[ 1.593046] EXT4-fs (sdb1): couldn't mount as ext3 due to feature incompatibilities
[ 1.599792] EXT4-fs (sdb1): mounting ext2 file system using the ext4 subsystem
[ 1.614366] EXT4-fs (sdb1): mounted filesystem without journal. Opts: (null)
[ 1.618589] VFS: Mounted root (ext2 filesystem) readonly on device 8:17.
[ 1.626643] devtmpfs: mounted
[ 1.665158] Freeing unused kernel memory: 1216K
[ 1.667934] Write protecting the kernel read-only data: 18432k
[ 1.670772] tsc: Refined TSC clocksource calibration: 2207.976 MHz
[ 1.673349] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x1fd3a19a709, max_idle_ns: 440795259673 ns
[ 1.681441] Freeing unused kernel memory: 2004K
[ 1.693107] Freeing unused kernel memory: 1080K
[ 1.836603] modprobe (1041) used greatest stack depth: 14072 bytes left
[ 1.877586] rcS (1037) used greatest stack depth: 13984 bytes left
[ 2.683414] clocksource: Switched to clocksource ts
[ 333.025228] kworker/dying (178) used greatest stack depth: 13944 bytes left
除此之外没有输出。我在 rootfs.img 中创建了 etc/init.d/rcS
,其中包含以下内容:
#!/bin/sh
mount -t sysfs none /sys
mount -t configfs none /config
mount -t devtmpfs none /dev
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
echo "+++++++++++++++++++++++++++++++ HELLOO ++++++++++++++++++++++++++++++"
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
EDIT2
我从 GRUB 配置中删除了 console=tty0
,内核引导至 shell。但是我不确定为什么会导致在这个虚拟环境中挂起?
我在想,因为 tty0
代表当前显示,并且因为 -display none
是为 qemu 设置的,所以这种混淆会产生一些冲突,因此这个问题...
但是请有人就此问题给出正确和具体的结论,以便此线程将来对某人有用。
您在整个卷(文件)上创建了文件系统,而不是在分区上。如果你想把它放在一个分区上,那么你必须在文件中写一个分区 table 并在分区中创建文件系统。
编辑。不确定 grub 是否可以在没有 GPT 或 MBR 的情况下启动。
要使用此图像分区,请创建一个 1MB 的大文件,将 GPT 分区 table 写入第一个兆字节,使用 dd 将图像复制到其余部分。
dd obs=1M seek=1 rootfs.img newroot.img
我可以使用 -kernel
在 QEMU 上启动 linux 内核,这非常简单明了。
但现在我正在尝试不同的东西。我模拟的是UEFI+GRUB+Kernel的组合
我已经从源代码构建了 OVMF 和 GRUB2,也能够加载内核映像,但是在创建 rootfs 磁盘映像并将其附加到 qemu 以便内核检测到它时遇到困难。
这就是我为内核准备 rootfs.img 的方式:
#Create an empty ext2 disk image of size 10M
dd if=/dev/zero of=rootfs.img bs=1M count=10
mke2fs -j rootfs.img
#Populate the disk
mkdir /mnt/rootfs
mount -o loop rootfs.img /mnt/rootfs
rsync -a busybox/_install/ /mnt/rootfs
chown -R root:root /mnt/rootfs
sync
umount /mnt/rootfs
这是我的 GRUB 配置的样子:
menuentry "Linux Kernel Boot" {
set root=(hd0,msdos1)
linux (hd0,msdos1)/bzImage-x86_64 root=/dev/sdb1 rootwait console=ttyS0,115200n8 console=tty0
}
这是我用来启动 qemu 的命令:
qemu-system-x86_64 -m 2G -drive if=pflash,format=raw,readonly,file=OVMF_CODE.fd -drive if=pflash,format=raw,file=OVMF_VARS.fd -net none -serial stdio -display none -hda fat:disk -drive file=rootfs.img,index=1
我附加为 hda
的 FAT 磁盘包含我的 GRUB 和内核映像。我想要一个单独的磁盘用于 rootfs,并且不想为此目的使用此 FAT。
安装程序引导至内核,但内核无法挂载磁盘 sdb1
,因此在 rootfs 中看不到 init
,因此出现内核崩溃。以下是内核日志:
[ 1.030290] NET: Registered protocol family 17
[ 1.033540] ata1.01: configured for MWDMA2
[ 1.042119] Key type dns_resolver registered
[ 1.045150] scsi 0:0:0:0: Direct-Access ATA QEMU HARDDISK 2.5+ PQ: 0 ANSI: 5
[ 1.049509] sched_clock: Marking stable (1049235510, 0)->(1378961625, -329726115)
[ 1.058429] registered taskstats version 1
[ 1.060917] Loading compiled-in X.509 certificates
[ 1.066242] sd 0:0:0:0: [sda] 1032192 512-byte logical blocks: (528 MB/504 MiB)
[ 1.070386] sd 0:0:0:0: Attached scsi generic sg0 type 0
[ 1.074945] sd 0:0:0:0: [sda] Write Protect is off
[ 1.079585] scsi 0:0:1:0: Direct-Access ATA QEMU HARDDISK 2.5+ PQ: 0 ANSI: 5
[ 1.082483] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 1.090820] Magic number: 0:346:692
[ 1.094970] sd 0:0:1:0: [sdb] 20480 512-byte logical blocks: (10.5 MB/10.0 MiB)
[ 1.097740] sd 0:0:1:0: [sdb] Write Protect is off
[ 1.101097] sd 0:0:1:0: Attached scsi generic sg1 type 0
[ 1.108436] console [netcon0] enabled
[ 1.110947] netconsole: network logging started
[ 1.114830] sd 0:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 1.122345] scsi 1:0:0:0: CD-ROM QEMU QEMU DVD-ROM 2.5+ PQ: 0 ANSI: 5
[ 1.138010] sda: sda1
[ 1.142638] sr 1:0:0:0: [sr0] scsi3-mmc drive: 4x/4x cd/rw xa/form2 tray
[ 1.145513] cdrom: Uniform CD-ROM driver Revision: 3.20
[ 1.149749] cfg80211: Loading compiled-in X.509 certificates for regulatory database
[ 1.164130] sd 0:0:1:0: [sdb] Attached SCSI disk
[ 1.169575] sr 1:0:0:0: Attached scsi generic sg2 type 5
[ 1.174262] sd 0:0:0:0: [sda] Attached SCSI disk
[ 1.190198] cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
[ 1.194508] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
[ 1.197606] cfg80211: failed to load regulatory.db
[ 1.200837] ALSA device list:
[ 1.203626] No soundcards found.
[ 1.531285] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input3
[ 1.537979] md: Waiting for all devices to be available before autodetect
[ 1.541357] md: If you don't use raid, use raid=noautodetect
[ 1.548186] md: Autodetecting RAID arrays.
[ 1.551815] md: autorun ...
[ 1.554889] md: ... autorun DONE.
[ 1.559995] VFS: Cannot open root device "sdb1" or unknown-block(8,17): error -6
[ 1.563196] Please append a correct "root=" boot option; here are the available partitions:
[ 1.566295] 0800 516096 sda
[ 1.566326] driver: sd
[ 1.572371] 0801 516064 sda1 be1afdfa-01
[ 1.572397]
[ 1.577560] 0810 10240 sdb
[ 1.577573] driver: sd
[ 1.582573] 0b00 1048575 sr0
[ 1.582585] driver: sr
[ 1.587948] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,17)
[ 1.590831] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.15.3+ #2
[ 1.593384] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 0.0.0 02/06/2015
[ 1.596327] Call Trace:
[ 1.600043] dump_stack+0x46/0x59
[ 1.602665] panic+0xca/0x218
[ 1.604991] ? printk+0x3e/0x46
[ 1.607197] mount_block_root+0x174/0x223
[ 1.609463] ? set_debug_rodata+0xc/0xc
[ 1.611851] mount_root+0xfb/0x104
[ 1.614159] prepare_namespace+0x130/0x166
[ 1.616415] kernel_init_freeable+0x1c5/0x1d7
[ 1.618676] ? rest_init+0xb0/0xb0
[ 1.621326] kernel_init+0x5/0xf0
[ 1.623768] ret_from_fork+0x35/0x40
[ 1.627035] Kernel Offset: 0x24800000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[ 1.632240] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,17)
有人可以指导在 qemu 中附加磁盘的正确方法来解决这个问题,或者我是否需要更改 GRUB 配置中的某些内容?
编辑
这次我按照@stark 的建议创建了分区table 的磁盘镜像
$ dd if=/dev/zero of=rootfs.img bs=1M count=10
#Using fdisk, created a partition of type Linux (83). This is how it looks now
$ fdisk -l rootfs.img
Disk rootfs.img: 10 MiB, 10485760 bytes, 20480 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xc08ab9b0
Device Boot Start End Sectors Size Id Type
rootfs.img1 2048 20479 18432 9M 83 Linux
$ sudo losetup -o 1048576 --sizelimit 10485248 /dev/loop23 rootfs.img
$ sudo mkfs.ext2 /dev/loop23
$ sudo mount /dev/loop23 /mnt/rootfs
$ sudo cp -vrf busybox/_install/* /mnt/rootfs/
$ sudo umount /mnt/rootfs
$ sudo losetup -d /dev/loop23
现在我再次使用与上面相同的命令启动内核,但这次内核只是挂起:
[ 1.593046] EXT4-fs (sdb1): couldn't mount as ext3 due to feature incompatibilities
[ 1.599792] EXT4-fs (sdb1): mounting ext2 file system using the ext4 subsystem
[ 1.614366] EXT4-fs (sdb1): mounted filesystem without journal. Opts: (null)
[ 1.618589] VFS: Mounted root (ext2 filesystem) readonly on device 8:17.
[ 1.626643] devtmpfs: mounted
[ 1.665158] Freeing unused kernel memory: 1216K
[ 1.667934] Write protecting the kernel read-only data: 18432k
[ 1.670772] tsc: Refined TSC clocksource calibration: 2207.976 MHz
[ 1.673349] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x1fd3a19a709, max_idle_ns: 440795259673 ns
[ 1.681441] Freeing unused kernel memory: 2004K
[ 1.693107] Freeing unused kernel memory: 1080K
[ 1.836603] modprobe (1041) used greatest stack depth: 14072 bytes left
[ 1.877586] rcS (1037) used greatest stack depth: 13984 bytes left
[ 2.683414] clocksource: Switched to clocksource ts
[ 333.025228] kworker/dying (178) used greatest stack depth: 13944 bytes left
除此之外没有输出。我在 rootfs.img 中创建了 etc/init.d/rcS
,其中包含以下内容:
#!/bin/sh
mount -t sysfs none /sys
mount -t configfs none /config
mount -t devtmpfs none /dev
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
echo "+++++++++++++++++++++++++++++++ HELLOO ++++++++++++++++++++++++++++++"
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
EDIT2
我从 GRUB 配置中删除了 console=tty0
,内核引导至 shell。但是我不确定为什么会导致在这个虚拟环境中挂起?
我在想,因为 tty0
代表当前显示,并且因为 -display none
是为 qemu 设置的,所以这种混淆会产生一些冲突,因此这个问题...
但是请有人就此问题给出正确和具体的结论,以便此线程将来对某人有用。
您在整个卷(文件)上创建了文件系统,而不是在分区上。如果你想把它放在一个分区上,那么你必须在文件中写一个分区 table 并在分区中创建文件系统。
编辑。不确定 grub 是否可以在没有 GPT 或 MBR 的情况下启动。
要使用此图像分区,请创建一个 1MB 的大文件,将 GPT 分区 table 写入第一个兆字节,使用 dd 将图像复制到其余部分。
dd obs=1M seek=1 rootfs.img newroot.img