3、QEMU快速上手:安装配置、基本命令行、启动一个虚拟机的完整流程

QEMU(Quick EMUlator)是当前硬件仿真与虚拟化领域使用最广泛的开源工具之一。它既支持纯软件模拟(TCG模式,即Tiny Code Generator),也支持基于硬件虚拟化(KVM、HVF、WHPX)的加速执行。对于嵌入式开发、操作系统内核调试、CI/CD自动化测试以及异构SoC(System on Chip,片上系统)功能验证而言,QEMU是性价比极高的起点。本章将围绕QEMU的安装策略、命令行参数体系以及从零启动一台虚拟机的完整操作链路展开,帮助学员建立从“工具安装”到“系统运行”的闭环认知。

QEMU 快速上手核心链路 ① 安装配置 包管理 / 源码编译 ② 镜像准备 qcow2 / raw / ISO ③ 命令行启动 -machine -cpu -m -drive ④ 网络与外设 virtio-net / 串口 核心参数组(以 x86_64 为例) -machine pc-q35-8.2 virt / vexpress-a9 -cpu max / cortex-a72 -smp 4 -drive file=disk.qcow2 if=virtio -netdev / -device user,id=net0 virtio-net-pci 启动验证与排障入口 -nographic 串口重定向 -monitor QEMU 控制台 -d guest_errors 调试日志 -snapshot 临时写入模式 -S -s GDB 调试

上图展示了QEMU快速上手的四个核心阶段:安装配置、镜像准备、命令行启动、网络与外设。后续内容将围绕该链路逐一展开,并深入剖析关键参数与常见排障手段。

3.1 安装配置:多平台覆盖与版本选择策略

核心原理

QEMU的安装并非简单的“装一个软件包”,而是需要根据宿主机的操作系统、目标架构(x86_64、ARM、RISC-V等)以及使用场景(纯模拟、KVM加速、跨架构开发)来选择不同的安装源和组件。QEMU的软件包通常拆分为qemu-system-<arch>、qemu-user、qemu-utils等子包。例如在Debian/Ubuntu上,qemu-system-x86负责x86虚拟机,qemu-system-arm负责ARM开发板模拟,而qemu-user-static则用于运行交叉编译的Linux用户态程序。

操作流程

  1. Linux宿主机(Ubuntu/Debian):执行 sudo apt update && sudo apt install qemu-system qemu-utils。若需KVM加速,额外安装 qemu-kvm libvirt-daemon-system。
  2. macOS宿主机:使用Homebrew执行 brew install qemu,默认启用HVF加速。
  3. Windows宿主机:从官网下载安装包,或使用 winget install QEMU.QEMU。Windows下需注意WHPX(Windows Hypervisor Platform)的启用。
  4. 源码编译(高级):当需要定制特定架构支持或打补丁时,执行 ./configure --target-list=x86_64-softmmu,arm-softmmu && make -j$(nproc)。
版本选择经验:对于生产环境或CI系统,建议使用发行版自带的稳定版本(如QEMU 8.x),而非每日构建版。若需使用最新virtio-gpu或RISC-V向量扩展,再考虑源码编译。使用 qemu-system-x86_64 --version 确认版本号。

案例拆解:Ubuntu 22.04 安装并验证KVM加速

某嵌入式团队需要在CI服务器上快速启动x86虚拟机进行内核模块编译。服务器为Ubuntu 22.04,CPU支持硬件虚拟化。初始执行 qemu-system-x86_64 -enable-kvm 时报错 Could not access KVM kernel module: No such file or directory。分析发现宿主机未加载KVM模块。执行 sudo modprobe kvm_intel(Intel CPU)后,再次运行 ls -l /dev/kvm 确认设备节点存在。随后安装 qemu-kvm 包,并执行 qemu-system-x86_64 -machine accel=kvm -cpu host -smp 4 -m 4G -drive file=ubuntu.qcow2,format=qcow2,虚拟机启动时间从纯TCG模式的90秒缩短至15秒。复盘要点:KVM加速依赖宿主机内核模块、设备节点权限(需将用户加入 kvm 组)以及BIOS中的VT-x/AMD-V开启状态。

常见误区

  • 误区一:认为QEMU只能模拟与宿主机相同架构。实际上QEMU支持跨架构模拟(如x86宿主机模拟ARM),但性能较低。
  • 误区二:忽略 qemu-utils 包,导致缺少 qemu-img 工具,无法创建磁盘镜像。
  • 误区三:在容器内运行QEMU时未开启 --device=/dev/kvm 挂载,导致无法使用KVM。

3.2 磁盘镜像与固件准备:qemu-img 与启动介质

核心原理

虚拟机需要持久化存储介质。QEMU使用 qcow2 格式作为默认镜像格式,它支持写时复制(CoW)、快照、压缩和AES加密。而 raw 格式为裸设备映射,性能最好但占用空间大。对于固件,x86平台通常使用OVMF(UEFI固件)或SeaBIOS(传统BIOS),ARM平台则使用 virt 机器自带的固件或 u-boot。

操作流程

# 创建 10GB 的 qcow2 镜像
qemu-img create -f qcow2 ubuntu.qcow2 10G

# 查看镜像信息
qemu-img info ubuntu.qcow2

# 将 raw 镜像转换为 qcow2
qemu-img convert -f raw -O qcow2 disk.raw disk.qcow2

# 创建快照(仅 qcow2 支持)
qemu-img snapshot -c clean_state ubuntu.qcow2
qemu-img snapshot -l ubuntu.qcow2

案例拆解:从ISO安装Ubuntu Server

目标:在无图形界面的服务器上安装Ubuntu Server 22.04。使用 -cdrom 参数挂载ISO,并通过VNC远程访问安装界面。关键命令如下:

qemu-system-x86_64 \
  -machine pc-q35-8.2,accel=kvm \
  -cpu host \
  -smp 4 \
  -m 4096 \
  -drive file=ubuntu.qcow2,format=qcow2,if=virtio \
  -cdrom ubuntu-22.04.3-server-amd64.iso \
  -boot d \
  -vnc :1 \
  -netdev user,id=net0,hostfwd=tcp::2222-:22 \
  -device virtio-net-pci,netdev=net0

安装过程中,VNC客户端连接 宿主机IP:5901 即可看到图形界面。安装完成后,通过 ssh -p 2222 user@localhost 登录虚拟机。此案例中,hostfwd 将宿主机的2222端口转发至虚拟机的22端口,实现SSH访问。复盘经验:-boot d 表示优先从光驱启动;安装完成后应移除 -cdrom 参数,避免再次进入安装界面。

风险提示:使用 qcow2 快照功能时,若底层镜像文件被移动或删除,所有快照将失效。生产环境建议定期 qemu-img commit 将快照合并回基础镜像。

3.3 命令行参数体系:从最小启动到完整配置

核心原理

QEMU命令行参数遵循 -device、-drive、-netdev 等分组逻辑。理解参数的关键在于区分“机器定义”与“设备模型”。-machine 定义主板芯片组和固件类型,-cpu 定义处理器模型,-m 定义内存大小,-smp 定义CPU核数。设备则通过 -device 挂载到总线上。

最小启动命令(x86_64)

qemu-system-x86_64 \
  -m 512 \
  -drive file=minimal.qcow2,format=qcow2 \
  -nographic

该命令启动一个无图形界面的虚拟机,串口重定向到当前终端。-nographic 同时禁用图形输出和音频,适合纯命令行环境。

参数对比表

参数组常用选项说明典型场景
-machinepc-q35-8.2, virt, vexpress-a9定义主板模型、固件类型x86桌面、ARM开发板模拟
-cpuhost, max, cortex-a72指定CPU型号与特性KVM加速时使用 host
-drivefile=, format=, if=定义存储设备接口与镜像if=virtio 获得高性能
-netdevuser, tap, bridge配置网络后端user 模式适合NAT
-devicevirtio-net-pci, e1000挂载PCI/ISA设备virtio系列性能最佳
-displaynone, gtk, vnc图形显示后端服务器使用 vnc

常见误区

  • 误区一:混淆 -drive 与 -hda。-hda 是旧式IDE接口简写,新代码应使用 -drive file=...,if=virtio。
  • 误区二:在ARM模拟中直接使用x86的 -cdrom 参数,导致无法识别设备。ARM virt机器通常使用 -drive file=flash.img,if=pflash 加载固件。
  • 误区三:忽略 -machine 的 accel= 属性,导致KVM未启用,性能骤降。使用 -machine accel=kvm:tcg 可自动回退。

3.4 网络配置与串口调试:从user模式到tap桥接

核心原理

QEMU网络分为后端(-netdev)与前端(-device)。user 模式(SLIRP)实现用户态NAT,无需宿主机root权限,但性能较差且不支持外部主动连接。tap 模式创建虚拟网卡对,需要宿主机配置桥接或路由,性能接近物理网卡。串口通过 -serial 参数重定向,mon:stdio 将串口与QEMU monitor绑定到同一终端。

操作流程:配置tap网络

# 创建 tap 设备(需 root)
sudo ip tuntap add dev tap0 mode tap user $(whoami)
sudo ip link set tap0 up
sudo ip addr add 192.168.100.1/24 dev tap0

# 启动 QEMU 并连接 tap0
qemu-system-x86_64 \
  -netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
  -device virtio-net-pci,netdev=net0 \
  -drive file=ubuntu.qcow2,format=qcow2 \
  -m 2G

虚拟机内配置静态IP 192.168.100.2/24,网关指向 192.168.100.1,即可与宿主机互通。若需访问外网,宿主机需开启IP转发并配置NAT规则。

案例拆解:嵌入式ARM开发板的串口调试

某团队使用QEMU模拟 vexpress-a9 开发板,该板卡仅有串口输出。启动命令如下:

qemu-system-arm \
  -machine vexpress-a9 \
  -cpu cortex-a9 \
  -m 1G \
  -kernel uImage \
  -dtb vexpress-v2p-ca9.dtb \
  -drive file=rootfs.ext2,format=raw,if=sd \
  -append "console=ttyAMA0 root=/dev/mmcblk0 rw" \
  -serial mon:stdio

关键点:-serial mon:stdio 将串口输出显示在终端,同时QEMU monitor也绑定到同一输入。按 Ctrl+A C 可切换至monitor,输入 quit 退出。复盘经验:-append 参数中的 console=ttyAMA0 必须与 -serial 对应,否则内核日志无法输出。若需保存串口日志,使用 -serial file:serial.log。

排障技巧:当虚拟机启动后无任何输出时,首先检查 -serial 是否与内核 console= 参数匹配。其次使用 -d guest_errors 查看QEMU内部错误日志。最后确认 -machine 的型号是否与 -kernel 匹配(例如vexpress-a9需要对应 uImage 格式)。

3.5 实战:完整启动一个带图形界面的Ubuntu虚拟机

场景描述

目标:在开发机上启动一个Ubuntu 22.04桌面版虚拟机,要求支持GPU加速(virtio-gpu)、多核CPU、SSH端口转发以及共享文件夹。宿主机为Ubuntu 22.04,CPU支持KVM。

操作步骤

  1. 准备镜像:使用 qemu-img create -f qcow2 ubuntu-desktop.qcow2 30G 创建磁盘。
  2. 安装系统:挂载ISO并启动VNC安装,命令参考3.2节案例。
  3. 优化启动参数:安装完成后,使用以下命令启动:
qemu-system-x86_64 \
  -machine pc-q35-8.2,accel=kvm \
  -cpu host \
  -smp 4 \
  -m 8G \
  -drive file=ubuntu-desktop.qcow2,format=qcow2,if=virtio \
  -vga virtio \
  -display gtk \
  -netdev user,id=net0,hostfwd=tcp::2222-:22 \
  -device virtio-net-pci,netdev=net0 \
  -virtfs local,path=/home/user/shared,mount_tag=host0,security_model=passthrough,id=fs0
  1. 验证功能:在虚拟机内执行 mount -t 9p -o trans=virtio host0 /mnt/shared 挂载共享目录。执行 glxinfo | grep "OpenGL renderer" 确认virtio-gpu渲染正常。

结果对比与复盘

配置项初始配置优化后性能提升
CPU-cpu qemu64-cpu host约30%
磁盘if=ideif=virtio约50%
网络e1000virtio-net-pci约40%
显示-vga std-vga virtio2D/3D加速可用

复盘经验:-cpu host 直接透传宿主机CPU特性,但虚拟机迁移到不同CPU型号的宿主机时可能失败。共享文件夹使用 virtfs 时,security_model=passthrough 要求宿主机目录权限正确,否则虚拟机内无法写入。风险点:-display gtk 需要图形环境,若在SSH会话中启动,应改用 -display none -vnc :1。

3.6 常见误区与总结复盘

误区清单

  • 误区一:忽略 -machine 的 accel 属性,导致KVM未启用。检查方法:启动时观察日志是否包含 Using KVM for x86_64。
  • 误区二:在ARM模拟中直接使用 -kernel 加载 zImage,但未提供 -dtb 设备树文件,导致内核崩溃。ARM平台必须匹配 machine 与 dtb。
  • 误区三:使用 -snapshot 参数后,所有磁盘写入仅保存在临时文件,重启后丢失。该参数适合测试,不适合持久化开发。
  • 误区四:混淆 -serial 与 -monitor。-serial 是虚拟串口设备,-monitor 是QEMU控制台。使用 mon:stdio 可同时复用终端。

总结复盘

QEMU快速上手的核心在于理解“机器-设备-后端”三层抽象。安装配置阶段需确认加速器可用性;镜像准备阶段需掌握 qemu-img 的格式转换与快照;命令行启动阶段需熟练组合 -machine、-cpu、-drive 等参数;网络与串口配置则决定了虚拟机的可访问性与调试便利性。建议学员在本地搭建一个最小化的x86虚拟机,逐步增加virtio设备、网络转发和共享目录,以此建立对QEMU参数体系的直觉。对于嵌入式场景,可进一步尝试 vexpress-a9 或 virt 机器,体会不同架构下固件加载与设备树配置的差异。