QEMU是一款跨平台的开源虚拟机工具,因为无GUI配置工具,有一定使用门槛
根据冯诺依曼结构,一个计算机可分为:
- 运算器
- 控制器
- 存储器
- 输入设备
- 输出设备
使用QEMU时,应该尽量往该模型联想。
创建存储器
创建一个16G的虚拟磁盘文件
qemu-img create -f qcow2 drive 16G
虚拟硬件环境
- 运算器、控制器 -> CPU、各种加速器*
- 输入、输出设备 -> 网卡、CXL设备等
QEMU本身没有像VMware那样的GUI配置界面,所有配置通过命令行参数指定
qemu-system-x86_64 -machine q35 \
-smp 4,sockets=1,cores=4,threads=1 \
-m 4096
现在启动了一个机型为q35,处理器1插槽4核4线程,内存4096MB,使用默认网络配置的虚拟机,由于没有启动盘,并不会启动某个系统
利用虚拟硬件环境启动系统
我们已经有了一块硬盘drive作为启动盘,指定给虚拟环境:
qemu-system-x86_64 -machine q35 \
-smp 4,sockets=1,cores=4,threads=1 \
-m 4096 \
-drive file=drive
会发现,指定后并没有什么区别,是因为这个“硬盘”我们没有给它“安装”系统。
安装系统
参考为物理机安装系统:
- 物理机硬盘 -> 虚拟磁盘文件drive
- 安装媒介(写入了镜像的U盘) -> 系统镜像文件
qemu-system-x86_64 -machine q35 \
-smp 4,sockets=1,cores=4,threads=1 \
-m 4096 \
-drive file=drive \
-drive file=<系统镜像,如ubuntu-22.04.2-live-server-amd64.iso>,media=cdrom
按照ISO文件的引导进行安装即可,完成后可移除ISO文件重启。
用qemu验证自己制作的iso镜像
qemu-system-x86_64 -cdrom testbios.iso -boot d
-
-cdrom testbios.iso 部分
cdrom是一个参数选项,用于告诉 Qemu 模拟器将指定的文件作为虚拟光盘来加载。在这个例子中,testbios.iso是要加载的 ISO 镜像文件。Qemu 会将这个 ISO 文件视为一个插入虚拟光驱的光盘,这样在模拟的计算机系统启动时,就可以从这个虚拟光盘中读取数据,就像在真实的计算机上从物理光盘启动一样。 -
-boot d 部分
boot是用于指定启动设备顺序的参数。d表示从光盘(CD - ROM 或 DVD - ROM,在这里是虚拟光盘,即前面指定的testbios.iso文件)启动。这意味着当 Qemu 启动模拟的计算机系统时,它会首先尝试从加载的 ISO 镜像文件中寻找引导程序来启动系统,就如同在真实的计算机上设置从光盘驱动器优先启动一样。
qemu启动kernel
总结qemu启动linux kernel的几种方式:
- 用
-kernel
和-initrd
指定内核和文件系统
参考:https://cloud.tencent.com/developer/article/2347447
qemu-system-x86_64
-s
-kernel ~/qemu/linux-4.9.263/arch/x86/boot/bzImage
-initrd ~/qemu/initramfs-busybox-x64.cpio.gz
--append "nokaslr root=/dev/ram init=/init"
为什么需要initramfs:
https://blog.csdn.net/fuhanghang/article/details/128849560
Linux启动阶段,boot loader加载完内核文件vmlinuz之后,便开始挂载磁盘根文件系统。挂载操作需要磁盘驱动,所以挂载前要先加载驱动。但是驱动位于
/lib/modules
,不挂载磁盘就访问不到,形成了一个死循环。
initramfs
根文件系统就可以解决这个问题,其中包含必要的设备驱动和工具,boot loader会加载initramfs到内存中,内核将其挂载到根目录,然后运行/init
初始化脚本,去挂载真正的磁盘根文件系统。
initrd 和 initramfs 原理浅析:
https://blog.csdn.net/Vallelonga/article/details/145534152
[Linux Kernel] initrd && initramfs 的区别 (ram disk;ramfs;tmpfs;rootfs):
====> B站视频
cpio归档:
- 简单的归档格式:
cpio
(copy in, copy out)是一种非常基础的归档格式,它只是简单地将文件和目录打包成一个连续的数据流。这种简单性使得cpio
在各种系统和环境中都能被方便地处理和解析。 - 广泛支持:许多 Linux 发行版和内核开发环境都对
cpio
格式有很好的支持。在构建initramfs
时,使用cpio
可以确保生成的文件能够被内核正确识别和加载。
使用方式:
- 进入 busybox 编译成果目录
cd ~/Desktop/initramfs/busybox-1.32.1/_install
- 使用 cpio 制作成 rootfs
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ~/Desktop/initramfs/initramfs-busybox-x64.cpio.gz
注意:该命令一定要在busybox的 _install 目录下执行
对比之前嵌入式linux中通过nfs挂载根文件系统:
与
initramfs
需要将文件系统打包成一个归档文件并加载到内存中不同,NFS 是直接通过网络实时访问服务器上的文件系统。因此,不需要将根文件系统进行归档(如.cpio
格式)和压缩(如.gz
),服务器上的文件系统可以以原始的文件夹和文件形式存在。
2.以镜像方式启动
QEMU 作为一款强大的开源虚拟机模拟器,除了使用 -kernel 和 -initrd 选项启动外,还可以直接使用镜像文件启动虚拟机。
=以镜像文件启动的原理=:
镜像文件通常包含了完整的操作系统,包括内核、文件系统、用户数据等。QEMU 可以直接模拟硬件环境,加载并运行镜像文件中的操作系统,就像在真实硬件上安装和启动操作系统一样。这种方式类似于在物理机上使用硬盘、U 盘 等存储设备中的操作系统进行启动。
-hda
示例:qemu-system-x86_64 -hda my_disk.img
这个命令将 my_disk.img 作为第一个 IDE 硬盘连接到 x86_64 架构的虚拟机。
是 QEMU 早期就存在的选项,为了向后兼容,在很多简单的使用场景中仍然被广泛使用。它的语法简单,适合初学者快速上手。-drive
-drive file=<系统镜像,如ubuntu-22.04.2-live-server-amd64.iso>,media=cdrom
随着 QEMU 功能的不断扩展,为了支持更多的磁盘设备类型和配置选项而引入的。它提供了更强大的功能,但语法相对复杂一些。
综上所述,如果你只需要简单地将一个磁盘镜像作为第一个 IDE 硬盘连接到虚拟机,使用 -hda
选项即可;如果需要更精细的磁盘设备配置,或者要连接多个不同类型的磁盘设备,建议使用 -drive
选项。
使用 qemu + gdb 调试 linux kernel 时,qemu的启动命令需要加上-s
,-S
:
-
-s
是 -gdb tcp::1234 的缩写。这个选项的作用是在 TCP 端口 1234 上启动一个 GDB 服务器,允许你使用 GDB(GNU Debugger)远程连接到 QEMU 虚拟机,对运行在其中的 Linux 内核进行调试。 -
-S
选项的作用是让 QEMU 在启动时暂停 CPU 的执行,直到你通过 GDB 连接到 QEMU 并发送继续执行的命令。也就是说,使用 -S 选项后,QEMU 会停在初始状态,等待调试器的指令再开始运行。
同时使用 -s
和 -S
选项时,QEMU 会在 TCP 端口 1234 上启动 GDB 服务器,并且在启动时暂停 CPU 的执行。你可以使用 GDB 连接到这个服务器,设置好断点和其他调试配置后,再让系统开始执行。以下是一个使用 GDB 连接到 QEMU 并继续执行的示例:
# 启动 QEMU
qemu-system-x86_64 -kernel vmlinuz -initrd initrd.img -s -S
# 打开另一个终端,使用 GDB 连接到 QEMU
gdb vmlinux
(gdb) target remote :1234
(gdb) break start_kernel # 设置断点
(gdb) continue # 继续执行
用 qemu 启动内核时,常用的选项如下:
- -m, 指定 RAM 大小,默认 384M
- -kernel,指定内核镜像文件 bzImage 路径
- -initrd,设置内核启动的内存文件系统
- -smp [cpus=]n[,cores=cores][,threads=threads][,dies=dies][,sockets=sockets][,maxcpus=maxcpus],指定使用到的核数。
- -cpu,指定指定要模拟的处理器架构,可以同时开启一些保护,如
- +smap,开启 smap 保护
- +smep,开启 smep 保护
- -nographic,表示不需要图形界面
- -monitor,对 qemu 提供的控制台进行重定向,如果没有设置的话,可以直接进入控制台。
- -append,附加选项
- nokaslr 关闭随机偏移
- console=ttyS0,和 nographic 一起使用,启动的界面就变成了当前终端。
举例:
#!/bin/sh
qemu-system-x86_64 \
-m 64M \
-nographic \
-kernel ./bzImage \
-initrd ./rootfs.img \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 kaslr" \
-smp cores=2,threads=1 \
-cpu kvm64