3、QEMU快速上手:安装配置、基本命令行、启动一个虚拟机的完整流程
QEMU(Quick EMUlator)是当前硬件仿真与虚拟化领域使用最广泛的开源工具之一。它既支持纯软件模拟(TCG模式,即Tiny Code Generator),也支持基于硬件虚拟化(KVM、HVF、WHPX)的加速执行。对于嵌入式开发、操作系统内核调试、CI/CD自动化测试以及异构SoC(System on Chip,片上系统)功能验证而言,QEMU是性价比极高的起点。本章将围绕QEMU的安装策略、命令行参数体系以及从零启动一台虚拟机的完整操作链路展开,帮助学员建立从“工具安装”到“系统运行”的闭环认知。
上图展示了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用户态程序。
操作流程
- Linux宿主机(Ubuntu/Debian):执行
sudo apt update && sudo apt install qemu-system qemu-utils。若需KVM加速,额外安装qemu-kvm libvirt-daemon-system。 - macOS宿主机:使用Homebrew执行
brew install qemu,默认启用HVF加速。 - Windows宿主机:从官网下载安装包,或使用
winget install QEMU.QEMU。Windows下需注意WHPX(Windows Hypervisor Platform)的启用。 - 源码编译(高级):当需要定制特定架构支持或打补丁时,执行
./configure --target-list=x86_64-softmmu,arm-softmmu && make -j$(nproc)。
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 同时禁用图形输出和音频,适合纯命令行环境。
参数对比表
| 参数组 | 常用选项 | 说明 | 典型场景 |
|---|---|---|---|
-machine | pc-q35-8.2, virt, vexpress-a9 | 定义主板模型、固件类型 | x86桌面、ARM开发板模拟 |
-cpu | host, max, cortex-a72 | 指定CPU型号与特性 | KVM加速时使用 host |
-drive | file=, format=, if= | 定义存储设备接口与镜像 | if=virtio 获得高性能 |
-netdev | user, tap, bridge | 配置网络后端 | user 模式适合NAT |
-device | virtio-net-pci, e1000 | 挂载PCI/ISA设备 | virtio系列性能最佳 |
-display | none, 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。
操作步骤
- 准备镜像:使用
qemu-img create -f qcow2 ubuntu-desktop.qcow2 30G创建磁盘。 - 安装系统:挂载ISO并启动VNC安装,命令参考3.2节案例。
- 优化启动参数:安装完成后,使用以下命令启动:
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
- 验证功能:在虚拟机内执行
mount -t 9p -o trans=virtio host0 /mnt/shared挂载共享目录。执行glxinfo | grep "OpenGL renderer"确认virtio-gpu渲染正常。
结果对比与复盘
| 配置项 | 初始配置 | 优化后 | 性能提升 |
|---|---|---|---|
| CPU | -cpu qemu64 | -cpu host | 约30% |
| 磁盘 | if=ide | if=virtio | 约50% |
| 网络 | e1000 | virtio-net-pci | 约40% |
| 显示 | -vga std | -vga virtio | 2D/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 机器,体会不同架构下固件加载与设备树配置的差异。