qemu使用

yuanheci 2024年11月30日 178次浏览

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的几种方式:

  1. -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