QEMU 是一个开源虚拟化项目,既能在一台 x86 电脑上模拟出另一台 x86 虚拟机,也能直接运行 ARM、RISC-V 等异构架构的系统镜像,还能作为普通虚拟机管理程序启动 Linux、Windows 以及麒麟 V10、统信 UOS 等国产操作系统。这篇文章从 QEMU 的两个核心工作模式讲起,先说明它为什么能做到跨架构,再给出 Linux 和 Windows 环境的安装方式,然后分别用最小命令跑通 x86、ARM64、RISC-V 三种架构的虚拟机,接着分析网络、磁盘和显示设备的工程化配置,最后整理常见的启动报错、排查顺序和生产环境建议。阅读这篇文章不需要太多前置知识,只要会用基础 Linux 命令行,就能跟着操作完成一个可运行的 QEMU 虚拟机。
1. 先理解 QEMU 的工作模式、加速器和多架构原理
QEMU 的定位不是单一的“虚拟机软件”,而是一套能够模拟 CPU、内存、外设和整机硬件的工具集。只有理解了它的工作模式,后面调试参数时才不会盲目试错。
1.1 全系统模拟与用户态模拟
QEMU 有两种主要工作模式。
第一种是全系统模拟(System Emulation)。它负责模拟出一台完整机器,包括 CPU、内存、磁盘控制器、网卡、显示适配器和 BIOS/UEFI 固件。虚拟机内部的操作系统认为自己运行在真实硬件上,实际上所有指令都会经过 QEMU 的翻译或加速器处理后执行。日常使用的qemu-system-x86_64、qemu-system-aarch64、qemu-system-riscv64都属于这个模式。
第二种是用户态模拟(User-mode Emulation)。这个模式只模拟 CPU 指令集,不模拟整机硬件,适用于在 x86 主机上直接运行 ARM 或 RISC-V 编译出来的单个可执行文件。典型命令是qemu-aarch64、qemu-riscv64。在嵌入式交叉编译和 CI 测试场景中,用户态模拟常被用来快速验证某个二进制文件能否在当前架构上运行,但它不能启动完整操作系统。
本文后面讲的都是全系统模拟,因为它的使用场景更广,也是很多人接触 QEMU 时的第一需求。
1.2 TCG、KVM、WHXP 与硬件加速的关系
QEMU 默认使用 TCG(Tiny Code Generator)做动态二进制翻译。它会把目标架构的指令翻译成宿主机 CPU 可以执行的指令,所以 x86 主机能够模拟 ARM、RISC-V 甚至 MIPS。TCG 的优势是跨架构能力强,代价是性能远低于本机执行。
如果宿主机和虚拟机架构一致,并且宿主机提供了硬件虚拟化能力,就可以绕过 TCG 使用“加速器”。Linux 下最常见的是 KVM,对应参数是-accel kvm。Windows 下常见的是 WHPX(Windows Hypervisor Platform),对应参数是-accel whpx。macOS 下可以使用 Hypervisor.framework,对应参数是-accel hvf。
判断是否真的用上了加速器,可以在 QEMU 启动命令里加-accel help查看当前环境支持的加速方式,也可以看启动日志中的-accel kvm是否成功启用。很多新手遇到“虚拟机极慢”的问题,根本原因就是 TCG 模式在纯软件翻译,而不是硬件加速。
| 加速器 | 所属平台 | 适用场景 | 启动参数示例 |
|---|---|---|---|
| KVM | Linux | x86 宿主运行 x86 虚拟机,性能接近原生 | -accel kvm |
| WHPX | Windows 10/11 | x86 宿主运行 x86 虚拟机 | -accel whpx |
| HVF | macOS | x86 宿主运行 x86 虚拟机 | -accel hvf |
| TCG | 所有平台 | 跨架构模拟,如 x86 上跑 ARM、RISC-V | 不写加速参数或-accel tcg |
1.3 QEMU 为什么能同时支持 x86、ARM、RISC-V
QEMU 把“机器模型”与“CPU 型号”拆开管理。机器模型决定主板上有什么设备,例如 ARM 的-M virt是一套虚拟化友好设备集合,RISC-V 的-M virt也是一套标准虚拟设备集合。CPU 型号决定指令集特性,例如 ARM 可以使用-cpu cortex-a57、-cpu neoverse-n1,x86 可以使用-cpu host或-cpu max。
因此,一套 QEMU 二进制程序可以对应多个目标架构。Debian/Ubuntu 的qemu-system元包会同时安装多个架构的系统模拟器,启动命令也会从qemu-system-x86_64、qemu-system-aarch64、qemu-system-riscv64等不同入口进入。理解这种分层设计后,就不会把“模拟器”和“某个架构”绑定死。
2. 环境准备:依赖、安装与基础校验
QEMU 在主流操作系统上都有安装方式。下面按 Linux 和 Windows 分别给出命令,然后在 2.4 节统一做版本和加速能力校验。
2.1 Debian/Ubuntu 系列安装
Debian/Ubuntu 可以直接使用软件源安装。推荐安装qemu-system和qemu-utils,前者提供全系统模拟器,后者提供qemu-img等镜像管理工具。
sudo apt update sudo apt install qemu-system qemu-utils如果只想安装某个架构的模拟器,可以精确安装子包:
sudo apt install qemu-system-x86 qemu-system-arm qemu-system-aarch64 qemu-system-riscv64安装完成后,先确认命令存在:
which qemu-system-x86_64 qemu-system-x86_64 --version2.2 CentOS/RHEL/Fedora 系列安装
在 Fedora 上可以直接用 dnf 安装:
sudo dnf install qemu-system-x86-core qemu-system-aarch64 qemu-system-riscv qemu-imgCentOS Stream 或 RHEL 使用 yum 时,包名可能稍有差异。如果源里没有 aarch64 或 riscv 子包,至少先安装主包,再通过模块源补齐。原项目或发行版文档没有明确指定版本时,落地前最好先执行一次dnf info qemu-system-*确认可用的包名称。
2.3 Windows 环境安装
Windows 下安装 QEMU 的方式是从官方发布页下载对应 Windows 的压缩包,解压后把包含qemu-system-x86_64.exe的目录添加到系统 PATH 环境变量。这里不建议把安装文件放到带空格或中文的路径下,避免后续脚本拼接命令时出现路径解析问题。
安装完成后,打开新的 PowerShell 或 CMD 窗口验证:
qemu-system-x86_64.exe --version如果命令找不到,检查是否在环境变量 PATH 中正确添加了 QEMU 的 bin 目录,并重新打开终端。
2.4 版本与加速状态校验清单
在开始创建虚拟机之前,建议花两分钟做一次环境检查,把问题和依赖项提前暴露出来。
| 检查项 | Linux 方法 | Windows 方法 |
|---|---|---|
| 基础命令可用 | qemu-system-x86_64 --version | 同上 |
| 多架构模拟器存在 | ls /usr/bin/qemu-system-* | dir QEMU安装目录 |
| KVM 设备存在 | ls -l /dev/kvm | 不适用 |
| WHPX 是否启用 | 不适用 | systeminfo查看 Hyper-V 相关选项 |
| 镜像工具可用 | qemu-img --version | qemu-img.exe --version |
注意:不要只验证“命令能输出版本号”就认为环境正常。跨架构虚拟机对 CPU、内存和固件文件的要求更高,后面每一次启动命令都值得单独验证。
3. 在 x86 主机上跑通 Linux 虚拟机
这一节用一个最小可运行场景打通从创建磁盘、启动安装到进入系统的完整链路,后续所有复杂参数都可以基于这条命令理解。
3.1 创建磁盘镜像
先用qemu-img创建一块精简分配的 qcow2 格式虚拟磁盘。qcow2 的特点是写多少占多少宿主机空间,同时支持快照和压缩。
qemu-img create -f qcow2 disk.qcow2 40G创建完成后查看磁盘信息:
qemu-img info disk.qcow2正常输出中virtual size是 40 GiB,disk size很小,说明还没有实际写入大量数据。这里不要把虚拟磁盘大小设置过小,Linux 桌面系统建议至少 40GB,服务器系统可以 20GB 到 30GB。
3.2 从 ISO 启动安装
准备好一个 Linux ISO,例如 Ubuntu Desktop 或 Debian 的安装镜像,然后用下面的命令启动虚拟机。
qemu-system-x86_64 \ -m 4096 \ -smp 4 \ -accel kvm \ -drive file=disk.qcow2,format=qcow2,if=virtio \ -cdrom /path/to/your-linux.iso \ -boot d \ -nic user,model=virtio-net-pci \ -display gtk启动后 QEMU 会打开图形窗口,虚拟机从光驱引导进入 ISO 安装界面。按正常 Linux 安装流程分区、设置用户、完成安装即可。安装完成后,去掉-cdrom和-boot d,再次启动就能进入磁盘系统。
qemu-system-x86_64 \ -m 4096 \ -smp 4 \ -accel kvm \ -drive file=disk.qcow2,format=qcow2,if=virtio \ -nic user,model=virtio-net-pci \ -display gtk3.3 常用启动参数拆解
很多初学者觉得 QEMU 命令难记,是因为没有拆解参数。每个参数的意义如下表所示。
| 参数 | 作用 | 常见值 | 说明 |
|---|---|---|---|
-m 4096 | 分配内存,单位 MB | 2048、4096、8192 | 内存不足会导致系统卡死或 OOM |
-smp 4 | 分配 CPU 核心数 | 2、4、8 | 不要超过宿主机物理核数 |
-accel kvm | 启用硬件加速 | kvm、whpx、hvf、tcg | 架构一致时优先硬件加速 |
-drive file=disk.qcow2,format=qcow2,if=virtio | 指定磁盘文件 | 可加cache=writeback | if=virtio性能更好 |
-cdrom xxx.iso | 挂载光驱 | 实际 ISO 路径 | 安装完成后建议移除 |
-boot d | 指定引导顺序 | d 表示光驱,c 表示磁盘 | 安装后改为磁盘引导 |
-nic user,model=virtio-net-pci | 配置用户态网络 | 可改用桥接网络 | 默认网关为 10.0.2.2 |
-display gtk | 图形显示前端 | gtk、sdl、none、vnc | 无桌面环境要用 vnc |
在 QEMU 的用户态网络模式下,虚拟机内部的默认网段通常是 10.0.2.0/24,虚拟机自己通常拿到的 IP 是 10.0.2.15,网关是 10.0.2.2。这个地址在网络排错时经常被提到,因此单独说明一下。
3.4 运行国产操作系统时的常见注意点
在 x86 虚拟机中安装麒麟 V10、统信 UOS 等国产操作系统,命令结构与普通 Linux 基本一致,但有几个细节容易出问题。
第一,引导固件。部分国产系统镜像要求 UEFI 启动,而 QEMU 默认是 SeaBIOS 传统引导。此时需要加-bios /usr/share/OVMF/OVMF_CODE.fd或使用对应的 UEFI 固件参数。第二,显示设备。某些系统桌面环境需要特定显示驱动,如果默认 VGA 花屏,可以尝试-vga virtio或-device virtio-vga。第三,磁盘控制器。老版本系统可能缺少 virtio 驱动,此时可以把if=virtio改成if=ide,先保证能安装进系统,再补驱动。
这些步骤不复杂,但需要在安装前确认系统镜像的引导方式是 UEFI 还是 legacy。判断错误时最常见的现象就是启动后黑屏或停在 GRUB 加载阶段。
4. 跨架构模拟:在 x86 主机上运行 ARM64 与 RISC-V
QEMU 的跨架构能力是它的重要卖点。在嵌入式开发、ARM 服务器软件适配和 RISC-V 实验场景中,经常需要在 x86 开发机上启动其他架构的完整系统。
4.1 在 x86 主机上跑一个 ARM64 虚拟机
先确认qemu-system-aarch64是否已安装:
which qemu-system-aarch64ARM64 虚拟机需要选择合适的机器模型和固件。最常用的是-M virt,它是一套为虚拟化优化的设备模型,配合 UEFI 固件使用。
qemu-system-aarch64 \ -M virt \ -cpu cortex-a57 \ -m 4096 \ -smp 4 \ -accel tcg,thread=multi \ -bios /path/to/QEMU_EFI.fd \ -drive file=arm64-disk.qcow2,format=qcow2,if=virtio \ -cdrom /path/to/arm64.iso \ -nic user,model=virtio-net-pci \ -serial mon:stdio这里的关键点是-cpu cortex-a57指定 ARM CPU 型号,-M virt指定虚拟机器模型。如果缺少-bios,很多 ARM64 镜像无法启动,因为它没有可用的固件入口。不同发行版提供的QEMU_EFI.fd路径不同,落地前要通过find / -name "QEMU_EFI.fd" 2>/dev/null确认实际路径。
由于 x86 宿主机模拟 ARM64 属于跨架构翻译,KVM 无法直接使用,默认会走 TCG 模式,速度比同架构虚拟机慢很多。学习、测试和 CI 验证可以接受,生产级性能则不推荐依赖 TCG。
4.2 运行一个 RISC-V 系统
RISC-V 是开放指令集架构,QEMU 的virt机器模型对 RISC-V 同样有完善支持。假设已经准备好 RISC-V 的 Linux 内核镜像Image和根文件系统rootfs.ext4,可以用类似命令启动:
qemu-system-riscv64 \ -M virt \ -m 2048 \ -smp 2 \ -kernel /path/to/Image \ -drive file=/path/to/rootfs.ext4,format=raw,if=virtio \ -append "root=/dev/vda rw console=ttyS0" \ -nographic-kernel直接加载内核,-append传入内核启动参数,console=ttyS0让内核输出到串口设备,-nographic则把串口重定向到当前终端。这种启动方式非常适合做 RISC-V 内核实验或操作系统课程设计,也常用于验证自己编译的 RISC-V 内核能否启动。
如果手上没有编译好的 RISC-V 内核和根文件系统,可以先从发行版构建系统下载预编译产物,或者参考官方提供的测试镜像。不同发行版的 RISC-V 根文件系统格式可能是 ext4、uboot 镜像或 squashfs,需要根据镜像类型调整-drive参数。
4.3 跨架构模拟的性能限制与接口差异
跨架构模拟的性能主要受 TCG 翻译效率影响。同样一台 x86 主机,跑 x86 虚拟机可以接近原生速度,跑 ARM64 虚拟机大概只能达到原生性能的十分之一甚至更低。这是动态二进制翻译的原理性限制,不是 QEMU 参数没调好。
另一个容易踩坑的地方是设备模型差异。-M virt下的 ARM64 和 RISC-V 默认不使用 PC 上的 IDE、VGA 等设备,网卡和磁盘控制器建议使用 virtio 设备。如果某个镜像在 ARM 下找不到磁盘,优先检查-drive的if=virtio和内核启动参数root=/dev/vda是否匹配。
注意:跨架构环境下的镜像、固件、内核和根文件系统必须属于同一个目标架构。把 x86 的 ISO 传给
qemu-system-riscv64,启动时会直接报错或卡死。
5. 网络、串口和显示的工程化配置
虚拟机启动只是第一步。真实开发中,用户需要 SSH 登录虚拟机、需要多台虚拟机互通、需要查看串口日志,还需要对磁盘做快照保护系统。这一节把这些工程化配置分开说明。
5.1 用户态网络与端口转发
QEMU 默认的-nic user模式已经提供了 NAT 网络。虚拟机可以主动访问外网,但宿主机无法直接访问虚拟机内部服务。解决方案是使用hostfwd做端口转发。
qemu-system-x86_64 \ -m 2048 \ -smp 2 \ -accel kvm \ -drive file=disk.qcow2,format=qcow2,if=virtio \ -netdev user,id=net0,hostfwd=tcp::2222-:22 \ -device virtio-net-pci,netdev=net0启动后,通过宿主机 2222 端口就能 SSH 到虚拟机的 22 端口:
ssh -p 2222 user@127.0.0.1这种模式适合单台虚拟机的开发和调试,不需要宿主机 root 权限,也不用手工创建网桥,是学习阶段最稳妥的网络方案。
5.2 桥接网络与多机互通
如果需要在宿主机、虚拟机以及多台虚拟机之间直接互通,推荐使用桥接网络。Linux 下可以通过ip命令创建网桥,再让 QEMU 使用 tap 设备接入网桥。
先准备宿主机网络环境:
sudo ip link add br0 type bridge sudo ip link set br0 up然后创建 tap 设备并挂到网桥:
sudo ip tuntap add dev tap0 mode tap sudo ip link set tap0 master br0 sudo ip link set tap0 upQEMU 启动时使用 tap 设备:
qemu-system-x86_64 \ -m 2048 \ -smp 2 \ -accel kvm \ -drive file=disk.qcow2,format=qcow2,if=virtio \ -netdev tap,id=net0,ifname=tap0,script=no,downscript=no \ -device virtio-net-pci,netdev=net0桥接模式需要宿主机具备足够的网络权限,脚本自动化时还要注意script=no,downscript=no,避免 QEMU 自带脚本干扰已经手工配置好的网桥。如果虚拟机内网卡始终无法获取 IP,先检查网桥和 tap 设备的链路状态,再在虚拟机内部执行ip addr查看网卡是否被识别。
5.3 串口重定向:没有图形界面也能调试
嵌入式开发和内核调试中,串口输出是最重要的观察窗口。QEMU 有几个常用串口参数。
-serial stdio把串口重定向到当前终端,适合命令行环境。
-serial mon:stdio把串口和 QEMU 监视器都放到当前终端,功能更完整。
用-nographic时,QEMU 会自动把串口绑定到当前终端,比较适合无显示环境的服务器。调试 ARM64 和 RISC-V guest 时,建议把内核启动参数中的console=ttyS0和-serial stdio一起使用,这样内核日志会输出到同一终端。
5.4 磁盘快照与系统恢复
qcow2 格式支持内部快照,可以在重大操作前保存磁盘状态。
qemu-img snapshot -c before-update disk.qcow2 qemu-img snapshot -l disk.qcow2从快照恢复:
qemu-img snapshot -a before-update disk.qcow2这些操作必须在虚拟机停机或磁盘没有被写入的情况下进行。不要在虚拟机运行期间直接对正在使用的disk.qcow2执行快照回滚,否则可能损坏文件系统。生产环境更推荐使用外部快照或备份整个镜像,配合定期备份策略使用。
6. 常见问题与排错链路
QEMU 的报错信息往往很短,但大多数问题都能从日志和参数中找到根因。下面按现象、原因、检查方式和处理建议组织。
6.1 KVM 不可用导致的启动失败
现象:启动命令报错Could not access KVM kernel module: Permission denied或/dev/kvm不存在。
可能原因:宿主机的 KVM 模块没有加载,或者当前用户没有/dev/kvm设备的访问权限。
检查方式:
ls -l /dev/kvm如果文件不存在,加载模块:
sudo modprobe kvm_intel如果是 AMD CPU,则加载kvm_amd。
如果文件存在但没有权限,把用户加入kvm组并重新登录:
sudo usermod -aG kvm $USER处理建议:先确认宿主机 CPU 是否支持虚拟化,再确认模块加载状态。虚拟机运行在 VMware Workstation 或 VirtualBox 内部时,还需要在宿主虚拟机设置中启用嵌套虚拟化。
6.2 Windows 下 WHPX 无法使用
现象:在 Windows 上执行-accel whpx启动失败,提示whpx: No accelerator found或failed to initialize WHPX。
可能原因:Windows 没有启用 Hypervisor Platform 功能,或者 Windows 版本不支持 WHPX。
检查方式:打开“启用或关闭 Windows 功能”,确认“Hypervisor Platform”已勾选。也可以使用系统信息命令查看。
处理建议:启用后重启系统,再回到 QEMU 命令确认加速器生效。如果仍然失败,可以暂时改用 TCG 验证虚拟机是否能启动,但要注意性能会明显下降。
6.3 跨架构虚拟机黑屏或串口无输出
现象:启动 ARM64 或 RISC-V 虚拟机后,图形窗口黑屏,终端也没有任何输出。
可能原因:缺少 UEFI 固件、机器模型选择错误、内核启动参数不正确,或图形设备型号不匹配。
检查方式:先用-serial stdio -display none去掉图形,专门看串口输出。如果串口有日志,就说明固件和内核已经启动,问题出在显示设备上;如果串口没有输出,优先检查-bios、-M和-cpu三个参数。
处理建议:不要一开始就追求图形界面。先让系统通过串口控制台正常启动,再补-display gtk或 VNC 显示参数。
6.4 Windows 虚拟机无网络或显示异常
现象:Windows guest 安装完成后没有网卡驱动,或显示分辨率异常、闪烁花屏。
可能原因:Windows 系统缺少 virtio 驱动,或者显示设备与 Windows 显卡驱动不匹配。
处理建议:安装 Windows guest 前准备 virtio-win 驱动镜像,在安装过程中通过“加载驱动程序”加载 virtio 网卡和磁盘控制器。显示异常可以尝试-vga virtio或-device vmware-svga,然后安装对应驱动。实际项目中推荐固定一套参数组合写入启动脚本,避免每次手动输入导致驱动识别不稳定。
6.5 排错清单速查表
| 现象 | 第一检查项 | 常用命令 | 处理方向 |
|---|---|---|---|
| KVM 权限不足 | /dev/kvm是否可写 | ls -l /dev/kvm | 加入 kvm 组 |
| 跨架构启动黑屏 | 固件和串口输出 | -serial stdio -display none | 先串口后图形 |
| Windows 无网络 | virtio 驱动是否加载 | 设备管理器中查看网卡 | 加载 virtio-win 驱动 |
| ARM64 找不到磁盘 | 内核 root 参数 | 查看串口内核日志 | 改root=/dev/vda |
| 虚拟机极卡 | 是否用了 TCG | -accel help | 架构一致时启用 KVM/WHXP |
| 磁盘回滚损坏 | 虚拟机是否运行中 | qemu-img snapshot -l | 停机后操作 |
7. 最佳实践与扩展方向
7.1 学习环境与生产环境的差异
学习阶段可以直接使用命令行参数启动虚拟机,状态文件放在当前目录,方便清理和重建。生产环境则需要额外考虑几件事。
- 配置外置化:启动参数不要写死在脚本里,使用变量或模板管理镜像路径、端口和 CPU 内存配额。
- 日志与监控:给 QEMU 加
-daemonize配合日志文件,或使用-D /var/log/qemu/qemu.log保存运行日志。 - 权限与安全:生产环境不建议用 root 直接运行 QEMU,建议为虚拟机分配独立系统用户。
- 虚拟机管理:单纯使用命令行维护多台虚拟机非常痛苦,建议引入
libvirt和virt-manager统一管理。 - 备份恢复:qcow2 内部快照不能替代外层备份,定期对镜像文件做离线备份。
注意:生产环境不要使用
-snapshot参数作为持久化方案,该参数会让所有写入都落在临时文件中,虚拟机重启后数据丢失。
7.2 用 libvirt 统一管理多虚拟机
libvirt是 QEMU 上层常用的管理接口,virt-manager则提供图形管理界面。使用 libvirt 后,虚拟机配置以 XML 形式保存,可以统一管理网络、存储池、快照和生命周期。
安装和启动服务:
sudo apt install libvirt-daemon-system virt-manager sudo systemctl enable --now libvirtd然后用virsh list --all查看虚拟机状态。生产环境建议先通过virsh define导入 XML 定义,再通过virsh start启动虚拟机,而不是直接写 QEMU 命令行。
7.3 扩展方向:嵌入式开发、CI 验证与架构适配
QEMU 还有一个非常重要的用途是嵌入式开发。可以利用 QEMU 模拟 ARM 开发板,配合-nographic和网络桥接,在宿主机编译内核,再启动到虚拟开发板中验证。这种方式在没有物理开发板的情况下,可以完成大部分驱动和系统集成验证工作。
在 CI 中,可以把 QEMU 作为跨架构测试执行环境。例如在 x86 的 GitLab Runner 上安装 QEMU,启动 ARM64 系统容器或虚拟机,验证产物在目标架构上的运行结果。这样能提前发现 x86 编译产物在 ARM 或 RISC-V 环境中可能出现的字节序、对齐和指令集问题。
对新手来说,比较有价值的练习路径是:先跑通 x86 Linux 虚拟机,然后尝试通过-nographic和串口调试 ARM64 虚拟机,最后编译一个 RISC-V 内核放到 QEMU 中启动。每一步都能加深对硬件虚拟化、指令集和 Linux 启动流程的理解。这套技能在嵌入式开发、操作系统课程和服务器架构适配中都会反复用到。