
你有没有经历过这样的时刻手头是一台普通的 x86 笔记本却拿到了一份 ARM64 架构的国产系统镜像或者刚分配了一块 RISC-V 开发板快递还没到但今晚就要验证一个启动流程。这时候QEMU 几乎是绕不开的选择。它可以模拟多种硬件架构也能在 x86 宿主上运行 Linux、Windows 和各类国产操作系统听起来确实很“万能”。但很多人第一次用它不是被命令行劝退就是卡在启动后没有输出、性能慢到无法忍受、图形界面黑屏这一类问题上。问题到底出在哪我见过不少初学者把时间花在记一条条可复用的命令上结果换个场景就失效。真正决定 QEMU 使用体验的不是你背了多少参数而是你有没有同时想清楚三件事架构匹配、加速后端、镜像管理。QEMU 不是“一个虚拟机软件”而是“硬件模拟器 虚拟机监控器”的组合。把这层关系搞明白后面所有操作才谈得上顺。1. 先搞清楚 QEMU 到底在解决什么问题1.1 全系统模拟和虚拟化的分界线QEMU 有两种完全不同的运行模式系统模拟器qemu-system-*模拟整台电脑包括 CPU、内存、外设、中断控制器可以完整启动一个操作系统。用户态模拟器qemu-*只模拟 CPU 和系统调用接口用来直接运行另一个架构编译出来的单个程序。很多人平时说“用 QEMU 跑虚拟机”默认指的是系统模拟器。真正关键的区别在底层当 QEMU 以纯软件方式运行时客户机指令会被 TCG 动态翻译成宿主机架构的指令所以 x86 主机可以模拟 ARM、RISC-V、MIPS 等不同架构。代价是性能明显偏低。而当你让 QEMU 模拟与宿主相同架构时它可以调用 KVMLinux或 WHPXWindows这类硬件虚拟化接口让虚拟机里的指令尽量直接在真实 CPU 上执行性能会接近原生。这个差别决定了你后续所有预期。如果你拿一台 x86 机器去模拟 ARM 系统就别指望它能像原生虚拟机一样流畅QEMU 的价值是把“启动链路能不能通”验证出来。如果只是想在 x86 上跑一个 Ubuntu 虚拟机优先启用 KVM/WHPX 才是正常用法。1.2 多架构支持带来的真实价值QEMU 的价值不是“可以多装一个虚拟机”而是把跨架构的软件验证变成一种可复现的流程。嵌入式团队在开发 ARM 程序时可以在 x86 的 CI 机器上用用户态模拟器跑单元测试内核开发者可以用qemu-system-aarch64先启动内核确认启动日志和驱动路径国产操作系统适配人员也可以在拿到真实硬件之前用 QEMU 完成镜像启动、安装、基础软件验证等工作。这些场景节省的不只是几小时而是把“必须依赖真实硬件”的前置条件打掉了。可以这么理解真实开发板是最终验收环境QEMU 是白天随时能拿出来做实验的迷你试验台。两者不是替代关系而是互补关系。2. 搭建最小运行环境从安装到第一条启动命令2.1 安装不同宿主的常见方式在 Ubuntu/Debian 系统上常见安装命令是sudo apt update sudo apt install qemu-system在 CentOS/RHEL 系列上可以使用yum install qemu。不过不同发行版的包拆分方式可能不同有的会把 x86、ARM、RISC-V 模拟器拆成独立包所以装完后建议先检查一下qemu-system-x86_64 --version qemu-system-aarch64 --version qemu-system-riscv64 --version如果某个架构的模拟器没有随包安装就需要单独安装对应的 QEMU 包。Windows 上可以到 QEMU 官网下载安装包也可以用包管理器。以 winget 为例可以先搜winget search qemu然后根据本机显示的包 ID 安装。安装完成后把 QEMU 安装目录加入PATH命令行里才能直接调用。macOS 上如果通过 Homebrew 安装通常是一条brew install qemu。这里多说一句安装本身不是难点难点在于有人装完发现qemu-system-aarch64不存在就想当然以为 QEMU 不支持 ARM。实际上多半是包没装全先检查模拟器文件再下结论。2.2 跑通第一个虚拟机的“最小命令”先用一个不带图形界面的 Linux 发行版 ISO 做测试。最简单的启动命令长这样qemu-system-x86_64 \ -m 1024 \ -cdrom /path/to/image.iso \ -boot d-m 1024表示分配 1GB 内存-cdrom挂载光驱镜像-boot d表示先从光驱启动。第一次验证不要贪大内存可以先给 1GBCPU 也可以不加。如果你想用一块虚拟硬盘来安装系统先创建磁盘镜像qemu-img create -f qcow2 disk.qcow2 20G然后启动qemu-system-x86_64 \ -m 2048 \ -hda disk.qcow2 \ -cdrom /path/to/install.iso \ -boot d按提示安装完系统后再启动时就不需要-cdrom和-boot d了直接指向硬盘镜像即可。这个流程是最小可用路径。它的作用不是展示 QEMU 的复杂能力而是让你先确认QEMU 本身没问题、镜像没问题、当前的输出方式能看到启动过程。如果这一步都跑不通后面调网络、调跨架构更无从谈起。2.3 为什么没有图形界面输出并不只有窗口很多人在服务器上跑 QEMU发现没有窗口弹出或者弹出一个黑窗口马上就消失就以为失败了。其实 QEMU 有多种显示输出方式GTK 或 Cocoa 图形窗口适合本机手动操作。VNC适合远程连接图形桌面。Spice适合需要更丰富远程协议的场景。串口模式适合纯文本调试和嵌入式场景。如果你在无显示器服务器上运行可以加-vnc :1然后用 VNC 客户端连到宿主机IP:5901。如果不需要图形界面只想看内核串口日志可以加-nographic或-serial stdio让串口输出直接进当前终端。初学者经常把“没有图形输出”和“虚拟机启动失败”混为一谈。排查时先确认你配置的是哪种输出方式再看是没输出还是输出后卡住。这两者处理思路完全不同。3. 真正拉开差距的是加速后端、镜像管理和网络3.1 KVM、WHPX、TCG 怎么选加速方式直接决定虚拟机能不能流畅跑。可以先看一张简单的对照表使用场景模拟器加速方式性能预期Linux x86 宿主机跑 x86 虚拟机qemu-system-x86_64KVM接近原生Windows x86 宿主机跑 x86 虚拟机qemu-system-x86_64WHPX可用但依赖 Hyper-V 平台组件x86 宿主机跑 ARM 虚拟机qemu-system-aarch64TCG明显慢适合功能与启动验证x86 宿主机跑 RISC-V 虚拟机qemu-system-riscv64TCG适合开发调试不适合重负载在 Linux 上先查看 KVM 是否可用ls -l /dev/kvm如果这个设备文件不存在说明 KVM 不可用或未加载内核模块。常见原因有三个BIOS/固件里关闭了虚拟化、内核没有加载kvm或kvm_amd/kvm_intel模块、当前用户不在kvm用户组里。在 Windows 上QEMU 会尝试使用 WHPXWindows Hypervisor Platform前提是系统功能里开启了“虚拟机平台”和“Windows 虚拟机监控程序平台”。如果你之前遇到 WSL2 报“此计算机上未启用虚拟化”那么 QEMU 的 WHPX 也可能同样不可用因为这两个功能共用底层虚拟化开关。排查顺序建议是进入固件设置确认 CPU 虚拟化Intel VT-x 或 AMD-V已开启。在 Windows 功能中启用“虚拟机平台”和“Windows 虚拟机监控程序平台”。重启后执行systeminfo查看输出里 Hyper-V 相关要求是否满足。重新运行 QEMU并在参数中显式指定-accel whpx看报错信息。如果确实没有硬件加速可用的环境QEMU 会自动落回 TCG也能运行只是性能会差很多。但要注意如果你在参数里写了-accel kvm或-accel whpx而环境不支持QEMU 会直接报错而不是悄悄降级。3.2 qcow2、raw 和磁盘镜像的增量玩法磁盘镜像的格式会影响性能、占空间和可维护性。raw 格式最接近物理磁盘性能好但占用空间大也不支持快照。qcow2 是 QEMU 最常用的格式默认稀疏分配也就是说创建 20G 的镜像实际只用多少占多少还支持快照、后端镜像、压缩等特性。创建 qcow2 镜像qemu-img create -f qcow2 base.qcow2 20G做批量测试时还可以基于一个基础镜像创建差量镜像qemu-img create -f qcow2 -b base.qcow2 -F qcow2 test1.qcow2这样test1.qcow2不复制基础镜像的全部数据而是把变化记录在差量文件里。多个测试实例可以共享同一个干净的基础系统互不污染。对于需要反复验证同一套软件行为的场景这个功能非常实用。3.3 网络和串口调试时最容易卡住的两个口QEMU 默认的用户模式网络user networking适合虚拟机共享宿主机网络上网也适合做端口转发。常见的转发写法qemu-system-x86_64 \ -m 2048 \ -drive filedisk.qcow2,formatqcow2 \ -netdev user,idn1,hostfwdtcp::2222-:22 \ -device virtio-net-pci,netdevn1这样宿主机上的2222端口会转发到客户机的22端口之后你就可以用ssh -p 2222 userlocalhost登录虚拟机不用开图形界面。串口则更像是嵌入式开发者的“眼耳口鼻”。如果你调试内核或者 bootloader通常需要把串口映射到终端qemu-system-aarch64 ... -serial stdio或直接用-nographic让 QEMU 把串口输出接到当前终端。这里有一个特别容易踩的坑客户机内核参数里的consolettyAMA0是告诉 Linux 内核日志从哪个串口出去而 QEMU 前端的-serial stdio是告诉 QEMU 把哪个物理串口映射到宿主终端。两边必须对齐否则你会在终端里什么都看不到。4. 跨架构模拟在 x86 上跑 ARM 和 RISC-V4.1 先区分系统模拟器和用户态模拟器qemu-system-aarch64是完整系统模拟可以启动一个完整的 ARM64 Linux 系统。qemu-aarch64是用户态模拟它只负责运行单个 ARM64 编译的程序不能启动完整系统。用户态模拟非常适合做交叉编译后的验证。比如你在一台 x86 机器上用交叉工具链编译了一个 ARM64 程序想快速确认它能不能运行就可以用qemu-aarch64 -L /usr/aarch64-linux-gnu ./hello-L指定交叉编译工具链的 sysroot 路径目的是让动态链接器找到正确的依赖库。这个用法在 CI 流水线里很常见因为不需要启动整个虚拟机速度更快资源占用也更小。不过要注意用户态模拟只能验证用户态程序不能验证内核、驱动和硬件相关逻辑。如果你想跑一个完整系统仍然需要qemu-system-aarch64。4.2 跑一个 ARM Linux 系统的基础流程完整跑 ARM64 Linux 有两种常见路径使用发行版提供的云镜像或 QEMU 镜像直接作为磁盘启动。手动准备内核、initrd 和根文件系统用-kernel参数手动引导。后者更适合内核调试示意命令如下qemu-system-aarch64 \ -M virt \ -cpu cortex-a57 \ -smp 2 \ -m 2048 \ -kernel Image \ -initrd initrd.img \ -append consolettyAMA0 root/dev/vda rw \ -drive filerootfs.qcow2,formatqcow2,ifvirtio \ -serial stdio这里的Image是 ARM64 Linux 内核的常见产物但在不同发行版、不同构建系统里文件名可能不一样。-M virt是 QEMU 提供的一个通用 ARM 虚拟开发板模型外设模型相对简单最适合做纯软件模拟和调试。如果你刚接触跨架构模拟我建议先使用现成的云镜像而不是手动编译内核。手动编译内核需要处理交叉工具链、内核配置、initramfs 等多个变量哪一个有问题都会让你误以为 QEMU 出了问题。先用现成镜像把启动链路跑通再逐步引入自己的内核会顺利很多。4.3 RISC-V 模拟适合干什么RISC-V 在 QEMU 里的成熟度这几年提升很快比如-M virt机器模型已经能跑 OpenSBI、U-Boot 和 Linux。可以用下面的命令思路启动一个 RISC-V 64 系统qemu-system-riscv64 \ -M virt \ -m 2G \ -smp 2 \ -kernel /path/to/Image \ -append consolettyS0 \ -drive filerootfs.qcow2,formatqcow2,ifvirtio \ -serial stdio但要注意边界QEMU 模拟的 RISC-V 外设模型没有 x86 那么丰富很多开发板上的私有外设、专有接口、复杂中断控制器都无法完全模拟。它更适合用来验证启动流程、跑基础 Linux 命令、做内核最小配置调试如果要做硬件相关驱动的全量验证还是需要在真实板子上跑。5. 在 Windows 上使用 QEMU 会遇到哪些坑5.1 虚拟化未启用WSL2 和 WHPX 共用一个开关Windows 下使用 QEMU最常见的报错就是和虚拟化相关的提示。比如 QEMU 启动时报“此平台不支持虚拟化的 AMD-V/RVI”或者 WSL2 之前已经报过“此计算机上未启用虚拟化”。这两类问题往往指向同一个底层原因系统虚拟化开关或 Windows 功能没有开全。我建议按这个顺序排查重启进入 BIOS/固件设置确认 Intel VT-x 或 AMD-V 已开启。在 Windows 功能里开启“虚拟机平台”和“Windows 虚拟机监控程序平台”。重启后运行systeminfo看 Hyper-V 要求部分是否提示“已检测到虚拟机监控程序”。再次用-accel whpx显式启动 QEMU观察报错是否变化。如果第 3 步仍然显示未检测到问题通常出在固件开关或 Windows 功能没有真正生效。不要急着换 QEMU 版本先确认这两个基础项。5.2 安装依赖缺失VC 运行库问题有些用户在 Windows 上安装 QEMU 时会遇到系统提示缺少 Microsoft Visual C 运行库。常见现象是安装包校验没问题但安装到一半报缺少某个运行库组件。这通常不是 QEMU 包的问题而是当前系统缺失公共运行库。处理思路比较简单去微软官网下载并安装最新的 Visual C Redistributable再重新安装 QEMU。如果系统里既有 32 位也有 64 位程序最好把 x86 和 x64 两个版本都装上避免不同软件各取所需。5.3 在 Windows 上跑 Linux 虚拟机还是直接用 WSL2这是一个经常被问的问题。WSL2 和 QEMU 定义不同WSL2 是一套与 Windows 深度集成的 Linux 运行环境适合跑终端命令、脚本、容器和常见开发工具QEMU 是通用虚拟机管理工具适合启动完整操作系统、调试内核、模拟不同硬件架构。如果你需要的是一个完整的 Linux 桌面环境或者要做内核启动调试QEMU 更合适如果只是想要一个顺手、省资源的 Linux 命令行环境WSL2 通常更轻量。两者不是替代关系可以共存。WSL2 出现问题并不代表 QEMU 也会出现问题因为两者虽然都依赖底层虚拟化但用户态组件、配置路径和启动方式并不同。6. 国产系统和嵌入式场景下QEMU 怎么用才顺手6.1 先确认镜像架构再选择模拟器现在不少国产操作系统会同时提供 x86_64 和 aarch64 两种架构的镜像比如麒麟 V10、统信 UOS 等。在 QEMU 里验证这些系统第一件事不是运行而是确认镜像架构。如果宿主是 x86_64要跑 aarch64 版镜像启动命令要使用qemu-system-aarch64而且只能以 TCG 纯软件方式模拟性能会明显低于同架构。为了获得更好的体验优选和宿主架构相同的镜像版本。如果你只是想验证某个软件在国产系统上的兼容性可以用用户态模拟器更快地跑单个程序而不需要启动完整桌面环境。但如果要验证安装流程、桌面环境、服务启动这些系统级行为还是用完整系统模拟。6.2 串口和-nographic是嵌入式调试的第一块基石在嵌入式 Linux 开发中QEMU 最常用的反而不是图形界面而是串口。比如很多基于 ARM 的开发板 BSP 文档里启动 QEMU 的命令类似qemu-system-arm \ -M vexpress-a9 \ -m 256M \ -kernel zImage \ -dtb vexpress-v2p-ca9.dtb \ -append consolettyAMA0 \ -nographic用串口模式而不是图形窗口更接近真实开发环境启动阶段有没有内核日志、分区能否挂载、串口交互是否正常一眼就能看出来。同时也可以放到脚本里自动收集日志方便做回归验证。6.3 用快照把测试环境“冻结”下来做国产系统适配时经常需要反复进入一个已知状态比如“刚装完操作系统”“已安装依赖”“已执行完一次安装脚本”。用 qcow2 镜像加快照可以把这个状态保存下来测试结束后快速恢复避免一次次重装系统。QEMU monitor 里可以使用savevm和loadvm也可以通过外部命令创建快照qemu-img snapshot -c clean-base disk.qcow2恢复时用qemu-img snapshot -a clean-base disk.qcow2这种“先做好干净状态再放心折腾”的思路比每次从安装介质重新开始高效得多。7. 排错手册我该从哪里查起7.1 一个四层定位框架遇到 QEMU 问题时不要急着调参数。先按下面的顺序把问题定位到某一层现象层是完全启动不了还是启动了但没输出、黑屏、网络不通、性能慢架构层QEMU 的模拟器架构、客户机镜像架构、guest 内核架构三者是否一致加速层是否成功启用 KVM/WHPX还是落回了 TCG显式指定-accel后有没有报错配置层内存、CPU、磁盘格式、设备模型、串口参数是否和客户机匹配这个顺序的价值在于很多新手一上来就怀疑参数写错了结果问题根本不在参数而在架构不匹配。比如用qemu-system-x86_64去启动一个 ARM64 镜像参数再正确也起不来。7.2 常见报错与初步处理思路下面是一些常见场面和初步排查方向启动时报Failed to initialize KVMKVM 不可用或权限不足。检查/dev/kvm、当前用户组或者临时改用-accel tcg验证是不是加速层问题。启动后黑屏无输出先确认输出方式是窗口、VNC 还是串口。如果是串口检查 guest 内核 console 参数是否和-serial对应。报Guest has not initialized the display可能只是显示初始化慢也可能显卡驱动没起来不要急着判定死机多等几秒或改用串口模式观察。磁盘镜像无法启动用qemu-img info disk.qcow2查看镜像格式、大小、快照信息确认不是文件损坏或格式不匹配。7.3 性能慢优先检查这几项性能慢是最常见的劝退点。优先检查五件事是否用了硬件加速如果 QEMU 落回 TCG性能会大幅下降。确认-accel参数和宿主支持状态。是否用了 virtio 设备Linux 客户机尽量使用 virtio 磁盘和网卡设备模型差异对吞吐影响很大。磁盘格式raw 格式通常比 qcow2 更快但功能少。如果快照不是刚需可以在追求性能时选用 raw。CPU 型号设置KVM 模式下可以用-cpu hostTCG 模式下通常用-cpu max。手动指定一个过低的老 CPU 模型会限制指令集。内存是否足够给客户机分配的内存不足时系统会频繁换页但也不能把宿主机内存全部占满否则两个系统一起卡。8. 把 QEMU 从“临时试一下”变成工作流的一部分8.1 先跑通最小系统再叠加需求我建议所有 QEMU 新手都遵循同一个节奏先跑通最小系统再逐步加功能。不要一开始就把网络、共享目录、声卡、USB 重定向全部配满。每一步增加一个变量出问题的时候才能快速判断是哪一层引入的。一个典型顺序是用默认参数跑通qemu-system-x86_64确认系统能启动。加入 virtio 磁盘和 virtio 网卡验证性能和网络。加入端口转发和 SSH让虚拟机可以无人值守访问。再加入 VNC 或 Spice处理图形界面需求。最后再考虑跨架构模拟、多虚拟机、自动化脚本。这个过程看起来很基础但恰恰是最稳的。8.2 用脚本固化命令当一条 QEMU 命令经过调试已经稳定可用后把它固化成脚本而不是每次手动敲一遍。脚本化的好处不只是省时间还能把参数、镜像路径、端口号这些关键信息变成可维护的配置。一个简单的启动脚本可以长这样#!/bin/bash exec qemu-system-x86_64 \ -m 2048 \ -smp 2 \ -drive filedisk.qcow2,formatqcow2,ifvirtio \ -netdev user,idn1,hostfwdtcp::2222-:22 \ -device virtio-net-pci,netdevn1 \ -display none \ -serial stdio注意脚本里的镜像路径、虚拟化加速选项、端口号都可能随着环境变化不要做成一个死模板。8.3 把 QEMU 纳入 CI 或自动化测试再进一步QEMU 完全可以成为自动化测试的一部分。在软件开发中你可以用 QEMU 启动一个干净的测试系统在虚拟机里执行安装脚本、运行测试用例、检查服务状态然后通过快照恢复到初始状态。这样既避免了宿主机被测试污染又能保证每次测试从同一个基线开始。跨架构验证也同样适用在 x86 的 CI 机器上用qemu-system-aarch64启动一个 ARM64 虚拟机跑完测试后直接销毁。速度不一定快但能提前发现很多“换个架构就崩”的问题。这类问题如果等到真实硬件才暴露排查成本往往高得多。QEMU 真正值得长期掌握的地方是它让你从“等硬件”变成“先模拟验证”。从嵌入式交叉编译到国产系统适配从内核调试到桌面虚拟化它都是一层很可靠的地基。如果你正准备开始我建议你先不要急着下载一个大而全的系统镜像而是找一个小型内核和一个根文件系统用-nographic把一条串口日志跑通。等你看到第一行 Linux 启动日志出现在终端里你对 QEMU 的理解就已经超过大多数只看过教程的人了。