当初第一次在 x86 机器上跑qemu-system-aarch64,看着屏幕上弹出 ARM64 版 Alpine 的安装界面,我是真有点兴奋的。后来又在 Windows 上拿 QEMU 装 openEuler 的 ARM 虚拟机,再后来干脆在手机 Termux 里折腾 QEMU,一路下来踩的坑比学的命令还多。如果你正在搜“qemu 操作”,大概率也是想搞清楚:怎么装、怎么启动、怎么跑 ARM64 系统、怎么在 Windows 或手机上用。这篇就把我实际验证过的流程和教训全部写出来,按场景给命令、给参数、给排查思路,你照着操作基本能一次跑通。
1. 先分清 QEMU 的两种工作模式,别等装完才发现用错了
很多人把 QEMU 理解成“虚拟机软件”,这个说法不算错,但会误导你的使用方式。QEMU 实际上分两条完全不同的路线:全系统模拟和用户态模拟。它们对应的命令不一样、应用场景不一样,连安装包都经常是分开的。
1.1 全系统模拟:把一整台机器演出来
我们平时说的qemu-system-x86_64、qemu-system-aarch64属于全系统模拟。它直接模拟一整台电脑:CPU、内存、主板芯片组、硬盘控制器、网卡、显卡、USB 控制器……客户机操作系统根本不知道自己跑在虚拟机里,它会像在真机上一样做硬件探测、加载驱动。
你可以用它做这些事:
- 在同一台 x86 电脑上运行 ARM64 版本的 Linux 发行版,比如 openEuler、Alpine、Debian 的 aarch64 镜像;
- 在没有 GUI 的服务器上跑一个纯命令行虚拟机做测试;
- 调试内核、交叉编译后的镜像,因为你可以完全控制机器参数;
- 模拟嵌入式设备的环境,比如 ARM 开发板。
全系统模拟的代价是性能开销大。CPU 每条指令都要经过翻译,后面我会详细讲。
1.2 用户态模拟:只翻译单个程序
另一条路线是用户态模拟,对应命令是qemu-aarch64、qemu-arm、qemu-x86_64这类不带-system的。它只模拟一个 CPU 和 Linux 的系统调用接口,用来直接运行单个可执行文件,不模拟整机。
典型用法是:
# 在 x86 Linux 上直接运行 ARM64 的二进制文件 qemu-aarch64-static ./my_arm64_program # 配合 binfmt_misc,可以直接执行 ARM 架构的程序 sudo update-binfmts --enable qemu-aarch64做嵌入式开发的人经常用它跑交叉编译产物,或者配合 Docker 在 x86 上构建多架构镜像。日常折腾虚拟机一般用不到用户态模式,但你得知道区别,否则找错命令很容易一脸懵。
1.3 TCG、KVM 和硬件加速到底怎么回事
QEMU 默认的翻译执行引擎叫 TCG(Tiny Code Generator),它是一种动态二进制翻译器:把客户机的 ARM 指令实时翻译成宿主机的 x86 指令。好处是跨架构也能跑,坏处是慢,通常比原生慢一个数量级以上。
如果想提速,需要硬件辅助虚拟化,这时候就要分清加速器:
| 加速器 | 所在平台 | 能不能跨架构 |
|---|---|---|
| KVM | Linux | 只能同架构,x86 宿主机只能加速 x86 客户机 |
| HVF | macOS | 一般只用于 x86 / x64 客户机 |
| WHPX | Windows | 同样只能加速 x86 客户机 |
| TCG | 所有平台 | 可以模拟任意架构,但无硬件加速 |
这里有个很容易误解的点:很多人以为在 x86 电脑上用 KVM 就能“加速模拟 ARM64”,不能。KVM 是让 CPU 直接运行客户机的同架构指令,ARM64 指令在 x86 CPU 上根本无法直接执行,所以跨架构模拟只能走 TCG。你会在 x86 上跑qemu-system-aarch64时看到它默认用 TCG,这是正常的,别去折腾 KVM 了。
明白了这个底层逻辑,后面遇到“为什么这么慢”“为什么 KVM 用不了”之类的问题,你自己就能判断了。
2. 装好 QEMU 之后,第一台虚拟机该怎么拉起来
我建议别一上来就玩 ARM64,先在你本机架构上跑通一个最简单的 Linux 虚拟机,把 QEMU 的基本操作搞熟。等你理解了启动参数的套路,再切到 ARM64 也不会慌。
2.1 不同平台的安装选择
QEMU 在各主流平台都有现成安装方式,我按平台列一下:
Linux(Debian/Ubuntu):
sudo apt install qemu-system-x86 qemu-system-arm qemu-utils,Fedora/RHEL 用dnf install qemu-kvm,这里注意 Debian 系把模拟器和工具拆得比较细。macOS:
brew install qemu,Homebrew 会一起装好常见固件和工具。Windows:去 qemu.org 下载官方 Windows 安装包,或者直接用包管理器:
winget install --id QEMU.QEMU -e安装完记得把安装目录加入 PATH,或者直接用完整路径调用
qemu-system-aarch64.exe。安卓 Termux:
pkg install qemu-system-aarch64 qemu-utils,后面专门有一节讲。
安装完测试一下:
qemu-system-x86_64 --version qemu-img --version看到版本号就说明基础环境没问题。
2.2 qemu-img:创建磁盘镜像的基本功
QEMU 不像 VirtualBox 那样有图形化向导,磁盘镜像是用命令创建的。我先说最常用的格式区别:
raw:就是裸数据,性能好,但不支持快照,多大文件占多大空间;qcow2:QEMU 独有的写时复制格式,创建时只占用实际写入的大小,支持快照、压缩、加密,是日常使用首选。
创建一块 8G 的 qcow2 磁盘:
qemu-img create -f qcow2 disk.img 8G查看镜像信息:
qemu-img info disk.img后面如果需要扩容:
qemu-img resize disk.img 12G注意 resize 只是调大镜像文件,客户机里面的分区表不会自动变,需进系统用分区工具扩展,这块到最后的坑位再展开。
2.3 一个最小可用启动命令
以 x86_64 宿主机跑 Alpine Linux 为例,先把安装 ISO 下载下来,然后执行:
qemu-system-x86_64 \ -m 2048 \ -smp 2 \ -enable-kvm \ -cdrom alpine-virt-3.20.0-x86_64.iso \ -drive file=disk.img,format=qcow2,if=virtio \ -netdev user,id=n1,hostfwd=tcp::2222-:22 \ -device virtio-net-pci,netdev=n1 \ -boot d \ -nographic这行命令的参数逐个解释一下:
-m 2048:内存 2G。-smp 2:两个 vCPU。-enable-kvm:Linux 宿主机且是 x86 客户机时使用硬件加速,速度会快很多。-cdrom:挂载 ISO 光驱。-drive file=disk.img,format=qcow2,if=virtio:挂载磁盘,接口用 virtio,性能比模拟 IDE 好。-netdev user,id=n1,hostfwd=tcp::2222-:22:用户态网络,并把宿主机的 2222 端口转发到客户机的 22 端口。-device virtio-net-pci,netdev=n1:给客户机添加一张 virtio 网卡。-boot d:优先从光驱启动。-nographic:不使用图形窗口,串口输出直接打到当前终端,适合服务器和无桌面环境。
装完系统后重启,去掉-cdrom和-boot d,从磁盘启动:
qemu-system-x86_64 \ -m 2048 -smp 2 -enable-kvm \ -drive file=disk.img,format=qcow2,if=virtio \ -netdev user,id=n1,hostfwd=tcp::2222-:22 \ -device virtio-net-pci,netdev=n1 \ -nographic主机上用ssh -p 2222 root@127.0.0.1就能连进虚拟机,用户态网络模式下客户机的 IP 固定是 10.0.2.15,端口转发都在宿主机 127.0.0.1 上监听,这个常识后面排查网络时会用到。
3. 真正折腾的开始:用 qemu-system-aarch64 模拟 ARM64
跨架构模拟是你搜索 QEMU 时最常碰到的话题,尤其是“qemu模拟arm64”。这个玩法在调试 ARM 软件、测试 aarch64 发行版时几乎是刚需。我先给你打好心理预期:这玩意儿跑起来是能用的,但不要指望它有物理机性能,一个简单的安装流程可能要等十几分钟甚至更久,属正常现象。
3.1 为什么跨架构模拟会这么慢
前面说了,TCG 要边翻译边执行,每条 ARM 指令都被拆成若干条 x86 微操作再来执行,等效于指令级解释。加上要模拟内存管理、中断、DMA 等,整个系统的开销非常大。
实测感受大概是:在 i5 级别的 x86 CPU 上跑 ARM64 Alpine 的文本安装界面,每一次按键响应都有明显延迟;如果跑带桌面的 openEuler,开机到登录可能要几分钟。这不是你命令写错了,纯粹是物理规律。
想缓解的话,可以:
- 用
-cpu max让 QEMU 启用支持的最大特性集,某些场景比固定cortex-a57更快; - 用 virtio 半虚拟化设备,别用模拟的 IDE 网卡;
- 内存和 CPU 别给太少,2G 内存两个核是最低要求;
- 不要同时开图形界面和多个后台任务。
3.2 跑通 Alpine ARM64 的完整启动命令
以宿主 Debian/Ubuntu 为例,先装好需要的固件:
sudo apt install qemu-system-arm qemu-efi-aarch64qemu-efi-aarch64提供 UEFI 固件,ARM64 的 virt 机器没有传统 BIOS,必须用 UEFI 引导,很多新手卡在这一步。
然后下载 ARM64 版 Alpine ISO:
wget https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/aarch64/alpine-virt-3.20.0-aarch64.iso qemu-img create -f qcow2 alpine-arm64.img 8G启动命令:
qemu-system-aarch64 \ -M virt \ -cpu max \ -m 2048 \ -smp 2 \ -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \ -cdrom alpine-virt-3.20.0-aarch64.iso \ -drive file=alpine-arm64.img,format=qcow2,if=virtio \ -netdev user,id=n1,hostfwd=tcp::2222-:22 \ -device virtio-net-pci,netdev=n1 \ -serial stdio -display none这里的参数有几点和 x86 不同:
-M virt:ARM64 下最通用的虚拟机型,没有具体主板型号,就是一个标准 ARM 虚拟平台。-cpu max:让 TCG 放开手脚启用所有支持的特性,兼容性最好。-bios:指定 UEFI 固件文件。不同发行版路径不一样,Debian 系常见于/usr/share/qemu-efi-aarch64/QEMU_EFI.fd,Fedora 系在/usr/share/edk2/aarch64/QEMU_EFI.fd。-serial stdio -display none:把串口输出到当前终端。如果你用-nographic要注意,ARM64 机器的串口设备名是ttyAMA0,某些发行版引导时需要追加console=ttyAMA0参数才能看到输出。
如果你发现串口没有显示,可以在 UEFI 启动菜单里按e编辑内核命令行,追加console=ttyAMA0。这个细节不同版本略有差异,按你实际镜像调整。
3.3 Alpine 的安装与网络检查
进入 Alpine 安装界面后,用root登录(默认无密码),执行:
setup-alpine按提示选择键盘、主机名、网络等。网络这里不用慌张,QEMU 的用户态网络会自动提供 DHCP,客户机一般能拿到 10.0.2.15 这个地址。
装到磁盘时执行:
setup-disk选择把系统写入/dev/vda,也就是我们挂载的 virtio 磁盘。写完后重启。
第二次启动时去掉光盘参数:
qemu-system-aarch64 \ -M virt -cpu max -m 2048 -smp 2 \ -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \ -drive file=alpine-arm64.img,format=qcow2,if=virtio \ -netdev user,id=n1,hostfwd=tcp::2222-:22 \ -device virtio-net-pci,netdev=n1 \ -serial stdio -display none登录后用:
ip a确认有eth0和 IP 地址,再测一下外网:
ping -c 3 223.5.5.5如果能通,说明网络没问题。之后你就能在客户机里apk add装各种软件了。
4. Windows 上装 openEuler ARM 虚拟机:一次完整的跨架构实操记录
“windows使用qemu安装openeuler arm虚拟机”是很多人搜的热词。为什么大家愿意在 Windows 上折腾这个?因为想体验 openEuler 的 ARM64 版本,但手头没有 ARM 服务器。我完整走了一遍,把链路整理出来,这里有个容易误导人的认知:QEMU 在 Windows 上可以模拟任意架构的客户机,但 WHPX 加速只对 x86 客户机有效,ARM64 客户机依然是纯 TCG 模拟,所以在 Windows 上装 openEuler ARM 会明显比本机架构慢,要有心理准备。
4.1 镜像下载与固件准备
openEuler 的 aarch64 ISO 去官方仓库找,比如 22.03 LTS 版本的 aarch64 目录:
https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/下载openEuler-22.03-LTS-aarch64-dvd.iso,文件比较大,接近 4GB,注意磁盘空间。
Windows 版 QEMU 安装包在qemu.org,装完后在安装目录的share子目录下一般能找到edk2-aarch64-code.fd,这就是 ARM64 的 UEFI 固件。如果找不到,我建议先在 WSL 或 Linux 机器上装一个qemu-efi-aarch64包,把固件拷过来用。这是比较稳妥的做法,别自己猜路径。
创建磁盘:
qemu-img create -f qcow2 openeuler-arm64.img 32GopenEuler 默认安装会比 Alpine 占空间,32G 起步比较安心。
4.2 启动安装的完整命令
Windows 上用 CMD 或 PowerShell 都行,注意 PowerShell 换行用反引号,CMD 用^。CMD 下命令是:
qemu-system-aarch64.exe ^ -M virt ^ -cpu cortex-a72 ^ -smp 4 ^ -m 4096 ^ -bios edk2-aarch64-code.fd ^ -cdrom openEuler-22.03-LTS-aarch64-dvd.iso ^ -drive file=openeuler-arm64.img,format=qcow2,if=virtio ^ -netdev user,id=n1,hostfwd=tcp::2223-:22 ^ -device virtio-net-pci,netdev=n1 ^ -device virtio-gpu-pci ^ -device virtio-keyboard-pci ^ -device virtio-tablet-pci ^ -vnc 127.0.0.1:1有两处我必须强调:
第一,ARM64 的 virt 机器默认没有显示设备和输入设备,你不加下面这三行,VNC 里会没有画面、没有键盘鼠标:
-device virtio-gpu-pci -device virtio-keyboard-pci -device virtio-tablet-pci第二,VNC 监听地址写成127.0.0.1:1是只允许本机连接,端口是 5901。别用:1的写法暴露到局域网,除非你知道自己在做什么。
用 VNC Viewer 连接127.0.0.1:5901,会看到 openEuler 的安装界面。安装过程里选择“服务器”或者带桌面的版本都可以,磁盘选我们挂载的 virtio 盘,软件源默认走光盘镜像,不用联网也能装完。
4.3 装完后的启动参数与使用建议
安装完成后,去掉-cdrom参数,再次启动:
qemu-system-aarch64.exe ^ -M virt ^ -cpu cortex-a72 ^ -smp 4 ^ -m 4096 ^ -bios edk2-aarch64-code.fd ^ -drive file=openeuler-arm64.img,format=qcow2,if=virtio ^ -netdev user,id=n1,hostfwd=tcp::2223-:22 ^ -device virtio-net-pci,netdev=n1 ^ -device virtio-gpu-pci ^ -device virtio-keyboard-pci ^ -device virtio-tablet-pci ^ -vnc 127.0.0.1:1如果你设置了打开 SSH 服务,宿主机直接:
ssh -p 2223 root@127.0.0.1整体感受是:安装阶段最煎熬,图形界面卡顿明显,建议耐着性子把必选项配置完就尽快跳到重启;进了系统以后,纯命令行 SSH 会话比 VNC 图形界面流畅得多,日常维护完全够用。
5. 手机上的极限操作:Termux 里装 QEMU 跑 ARM64
在手机上折腾 QEMU 属于“能跑就行”的快乐。我知道这很不实用,但你要是和我一样,出门在外想随时掏出手机看一眼 ARM64 环境,会理解这种执念。Termux 是安卓上的终端模拟器,它提供了完整的 Linux 用户态环境,能直接装 QEMU。
5.1 Termux 环境准备
首先更新源并安装软件包:
pkg update pkg install qemu-system-aarch64 qemu-utils这个包比较大,大概几百兆,建议在 Wi-Fi 环境下装。装完确认:
qemu-system-aarch64 --version再给 Termux 开放存储权限,方便把镜像放到共享目录:
termux-setup-storage镜像文件建议放在~/storage/downloads这样的位置,和电脑互传方便。
5.2 在 Termux 里启动 Alpine ARM64
手机性能有限,我建议跑最小化的 Alpine,不要跑桌面。用 Alpine 的 virt ISO 配合 UEFI 固件启动,命令和电脑上差不多:
qemu-system-aarch64 \ -M virt \ -cpu max \ -m 1024 \ -smp 2 \ -bios /data/data/com.termux/files/usr/share/qemu/edk2-aarch64-code.fd \ -cdrom alpine-virt-3.20.0-aarch64.iso \ -drive file=alpine-arm64.img,format=qcow2,if=virtio \ -netdev user,id=n1,hostfwd=tcp::2222-:22 \ -device virtio-net-pci,netdev=n1 \ -nographicTermux 的 QEMU 包一般会把固件装在$PREFIX/share/qemu/下,你可以先用find找一下:
find $PREFIX/share/qemu -name "*aarch64*"如果确实没有固件,退而求其次,下载 Alpine 的 aarch64 netboot 文件(vmlinuz-virt、initramfs-virt),用内核直载方式启动:
qemu-system-aarch64 \ -M virt -cpu max -m 1024 -smp 2 \ -kernel vmlinuz-virt \ -initrd initramfs-virt \ -append "console=ttyAMA0" \ -drive file=alpine-arm64.img,format=qcow2,if=virtio \ -netdev user,id=n1,hostfwd=tcp::2222-:22 \ -device virtio-net-pci,netdev=n1 \ -nographic这个方式的优点是省掉 UEFI 层,启动快一点点;缺点是 modloop(模块镜像)得自己处理,不同 Alpine 小版本的参数有差异。我的建议是:能搞到 UEFI 固件就用标准方式,省心。
5.3 手机模拟的性能和心态建议
实测在骁龙 8 系手机上,1024M 内存跑 Alpine ARM64 的安装,一个setup-alpine交互要等好几秒才刷新一次界面,输错一个字符都让你崩溃。更现实的做法是:
- 提前把安装命令想好,少打交互式命令;
- 或者直接在电脑上把系统装好,再把磁盘镜像传到手机上用;
- 把
-m调小到 768M,给手机系统留内存,免得整个机器卡死; - 不要开图形界面。
手机跑 QEMU 最大的价值不是性能,而是验证“ARM64 架构的软件在这个环境下的基本行为”。想真正干活,还是老老实实用电脑。
6. 这些坑我替你们踩过了:QEMU 常见问题的排查思路
最后这部分是纯干货,每个问题都是我在不同系统上切实遇到过的,我按“现象 → 原因 → 解法”的方式写,你可以直接对照。
6.1 提示 KVM 不可用或加速失效
现象:在 Linux 上启动虚拟机报:
Could not access KVM kernel module: No such file or directory kvm_init_vcpu failed: Invalid argument原因:宿主机的/dev/kvm不存在,或者 CPU 不支持嵌套虚拟化。
排查:
ls -l /dev/kvm cat /proc/cpuinfo | grep -c vmx解法:
- 物理机上装好 KVM 模块,或者确保用户在
kvm组; - 云服务器/虚拟机里跑 QEMU 要打开嵌套虚拟化选项;
- 如果只是跨架构模拟 ARM64,直接去掉
-enable-kvm,QEMU 默认会走 TCG。
要特别强调:x86 宿主机上模拟 ARM64,KVM 本来就帮不上忙,别在加速上浪费时间。
6.2 卡在 UEFI 黑屏或者找不到固件
现象:启动qemu-system-aarch64报:
Could not load ROM file: /usr/share/qemu-efi-aarch64/QEMU_EFI.fd或者启动后屏幕一直黑。
原因:没有安装 ARM64 的 UEFI 固件包,或者-bios路径写错了。
解法:
- Debian/Ubuntu 装
qemu-efi-aarch64; - Fedora 装
edk2-aarch64; - 确认固件路径后用
-bios指定绝对路径。
黑屏还有一个可能原因:你用了-display none但客户机的内核输出到了图形设备而不是串口。这时候把参数改成-serial stdio -display none,或者干脆开 VNC,能看到画面再判断。
6.3 客户机网络不通,SSH 连不上
现象:客户机能登录,但ping外网不通;或者宿主机ssh -p 2222 root@127.0.0.1连接被拒。
排查顺序:
- 客户机里先看
ip a,有没有拿到 10.0.2.x 地址; - 没有地址就执行
udhcpc -i eth0或者检查 DHCP 客户端; - 能 ping 通网关但上不了外网,检查宿主机 DNS,
/etc/resolv.conf是否正常; - SSH 连不上,先确认客户机里 sshd 启动了:
service sshd start; - 确认
hostfwd的宿主机端口没被占用:netstat -ano | findstr 2222(Windows)或ss -lntp | grep 2222(Linux)。
另外注意,用户态网络模式下,从宿主机连客户机只能用hostfwd转发的端口,不能直接连接客户机的 IP,因为 10.0.2.0/24 是 QEMU 内部的 NAT 网段。
6.4 磁盘空间不够,怎么给镜像扩容
现象:客户机提示磁盘满。
解法:先在宿主机扩大镜像:
qemu-img resize alpine-arm64.img +8G然后进客户机,扩展分区和文件系统。以 Alpine 的 ext4 为例:
# 查看分区情况 fdisk -l /dev/vda # 用 parted 或 fdisk 扩展分区,找到一个空闲空间并扩大分区 # 扩展根分区后让内核重读分区表 partprobe /dev/vda # 扩展文件系统 resize2fs /dev/vda2如果是 btrfs:
btrfs filesystem resize max /扩容这个操作没什么黑科技,就是分区工具 + 文件系统工具两件事。记住:resize 镜像文件只是把容器变大了,客户机里的分区表不会自动变。
6.5 进来慢、卡顿严重,有没有优化手段
除了换硬件,QEMU 侧能做的优化如下:
- 磁盘和网卡都用 virtio 设备,不要用
if=ide或模拟 e1000; - 尽量用
-cpu max而不是老旧的cortex-a57; - 给足内存,跨架构模拟场景 2G 内存和 1G 内存差距很大;
- 不需要图形的时候用
-nographic或-display none,图形渲染开销省掉一大截; - 如果是 x86 客户机在 x86 宿主机上,务必开 KVM,性能差距是数量级的。
我自己的习惯是:把所有常用的启动参数写成一个启动脚本放在项目目录里,避免每次敲一长串命令。比如 Linux 下写个run.sh,Windows 下写个run.bat,参数变更只改脚本即可。
最后的建议
QEMU 这东西,入门门槛主要不在命令,而在对“模拟 vs 虚拟化”的理解。你只要记住:同架构用 KVM 加速,跨架构认命用 TCG,设备尽量选 virtio,网络优先用 user 模式加端口转发,就足够应付绝大多数场景。我个人实际操作中,最常被问到的问题其实是“为什么这么慢”,每次回答完都会补一句:跨架构模拟能跑通已经是胜利,慢才是常态。希望这篇能帮你少走点弯路,少熬几个夜。