用途
QEMU 用户态模拟(user-mode)允许在一种架构的主机上运行另一种架构编译的二进制程序。该二进制作为普通进程运行,不涉及虚拟机,也不模拟内核,系统调用会被翻译到宿主内核。典型场景是在 ARM/ARM64 Linux 主机上运行 x86/i386 Linux 二进制(例如 netinstall-cli)。在 x86_64 Linux 上,内核原生支持运行 i386 二进制,因此无需 QEMU。
安装
不同平台对应的包与二进制名称如下:
- Debian/Ubuntu:包 qemu-user-static,二进制 qemu-i386-static
- Alpine:包 qemu-i386,二进制 qemu-i386
- Fedora/RHEL:包 qemu-user-static,二进制 qemu-i386-static
- 容器(tonistiigi/binfmt):无对应包,二进制 qemu-i386
注意:Debian/Ubuntu 使用 qemu-i386-static(静态链接,可复制进容器);Alpine 使用 qemu-i386(动态链接,必须留在主机或匹配的 rootfs 中)。
使用方式
直接调用时,在命令前加上 QEMU 二进制前缀,例如:
qemu-i386-static ./netinstall-cli -r -b -i eth0 routeros-7.22-arm64.npk
或使用显式路径:
/usr/bin/qemu-i386 ./my-x86-binary arg1 arg2
跨平台自动检测模式(优先级:本地二进制、静态(Debian)、动态(Alpine)):
for q in ./i386 qemu-i386-static qemu-i386; do
if [ -x "$q" ] || command -v "$q" >/dev/null 2>&1; then
QEMU="$q"
break
fi
done
if [ "$(uname -m)" = "x86_64" ]; then
QEMU=""
fi
${QEMU:+$QEMU} ./netinstall-cli [args...]
binfmt_misc(自动透明模拟)
Linux 的 binfmt_misc 可自动为外来二进制调用 QEMU。注册 QEMU 处理器通常由包安装或 Docker 设置完成,tonistiigi/binfmt 镜像为 Docker 执行此操作:
docker run --privileged --rm tonistiigi/binfmt --install all
注册后,外来二进制可透明运行,内核会自动调用 qemu-i386:
./my-i386-binary
在容器中:QEMU 二进制必须能在容器文件系统内访问。使用静态 QEMU(qemu-i386-static)时,将其复制进容器镜像;使用 binfmt 与 F 标志时,内核会预加载解释器。
容器内嵌
对于需要在 ARM 主机上运行 x86 二进制的容器,可将 QEMU 嵌入镜像:
crane export --platform linux/arm64 tonistiigi/binfmt:latest - | \
tar xf - usr/bin/qemu-i386
mv usr/bin/qemu-i386 rootfs/app/i386
chmod +x rootfs/app/i386
在容器内以如下方式调用:./i386 ./netinstall-cli [args...]
macOS:当用户态模拟不够用时
QEMU 用户态是 Linux 专有功能。在 macOS 上无法使用 qemu-i386 用户态。对于需要原始网络访问(特权端口上的 BOOTP/TFTP)的 Linux ELF 二进制,需要完整的 QEMU 系统虚拟机。
vmnet-bridged + 9p 模式:启动一个最小 Alpine Linux 虚拟机,桥接到 macOS 网络接口(L2 访问),并通过 9p virtfs 共享宿主工作目录。Linux 二进制在 x86_64 Linux 内原生运行,不使用用户态 QEMU。
关键组件:
- qemu-system-x86_64(brew install qemu)加 sudo(用于 vmnet-bridged)
- Alpine linux-virt 内核加自定义 initramfs(Alpine rootfs + 内核模块 + init 脚本)
- 内核模块通过 insmod 按显式依赖顺序加载(busybox 没有 modprobe)
- virtio_net 依赖 net_failover → failover(并不直观)
- 9p 依赖 9pnet_virtio → 9pnet → netfs
关键经验:
- 内核与模块须来自同一个 linux-virt APK,版本不匹配会破坏模块加载
- busybox insmod 无法加载压缩的 .ko.gz,需在构建时解压
- netinstall-cli 要求接口上有 IPv4 地址(可使用链路本地 169.254.1.1/16)
完整的 QEMU 启动命令、initramfs 构建过程、init 脚本与模块加载顺序,参见 macOS VM 桥接参考。
相关资源
参考文件:完整的 macOS VM 启动命令、initramfs 构建、init 脚本与模块加载顺序,参见 macOS VM 桥接参考。
相关技能:RouterOS CHR 系统级 QEMU(在虚拟机中运行完整 RouterOS)参见 routeros-qemu-chr 技能;构建内嵌 QEMU 的 OCI 镜像参见 tikoci-oci-image-building 技能;netinstall-cli 细节参见 routeros-netinstall 技能。