SuperAPI AI 工具集

tikoci-qemu-user-emulation

部署与运维

查看项目

更新于 10-16 07:29

技能介绍

用途

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 技能。