UTM:面向 iOS 与 macOS 的开源系统模拟器与虚拟机平台 —— 基于 QEMU 的架构、特性与构建全解析
【免费下载链接】UTMVirtual machines for iOS and macOS项目地址: https://gitcode.com/gh_mirrors/ut/UTM
本指南导读:UTM 是一个面向 iOS 与 macOS 的全功能系统模拟器与虚拟机宿主应用,底层基于 QEMU,可在 Mac、iPhone、iPad 上直接运行 Windows、Linux 等操作系统。本文将以其官方俄文 README 为主线,结合仓库源码(Architecture.md、Services、scripts 等),完整梳理 UTM 的核心特性、macOS 专属硬件加速能力、UTM SE 的 JIT-less 方案,以及从源码构建到打包签名的完整开发流程,帮助读者既会用 UTM,也能理解其底层原理。
一、项目定位:一个“通用机”的实现
UTM 的名字取自“通用图灵机”(Universal Turing Machine)。项目 README 开篇引用了艾伦·图灵 1936 年《论可计算数及其在判定问题上的应用》中的名句——“有可能发明一台能够计算任何可计算序列的单一机器”——这正是 UTM 的设计哲学:把“运行任意操作系统”的能力带到 Apple 生态中。
从仓库结构看,UTM 的技术栈可概括为三层(详见 Architecture.md):
- 引擎层:QEMU(模拟与虚拟化引擎),UTM 使用一个自定义 fork 维护,支持将 QEMU 构建为共享库、为越狱 iOS 提供 APRR 支持、集成 @ktemkin 的 ARM64 TCTI(无 JIT 的 iOS 支持)等 Darwin 专属优化;
- 后端抽象层:
UTMVirtualMachine提供跨平台一致的虚拟机视图(创建、保存.utm包、启停控制),其下分UTMQemuVirtualMachine(QEMU + CocoaSpice 后端)与UTMAppleVirtualMachine(Apple Virtualization.framework 后端,见 Services/UTMAppleVirtualMachine.swift); - 前端层:以 SwiftUI 2.0 为主(最低支持 iOS 14 / macOS 11),iOS 与 macOS 的 VM 显示视图则分别基于 UIKit 与 AppKit 实现。
二、核心特性全景
官方 README 列出的核心特性,在源码中均可找到对应实现:
1. 基于 QEMU 的完整系统模拟
UTM 提供完整系统模拟,包括 MMU(内存管理单元)、设备模拟等。QEMU 以共享库方式链接进应用:在 iOS 上因无法fork或直接使用 XPC,QEMU 主循环运行在 pthread 中;在 macOS 上则通过 XPC 在独立进程中启动(QEMUHelper与QEMULauncher负责沙盒引导),详见 Architecture.md。后端进程由 UTMQemuSystem 管理,它负责把UTMQemuConfiguration映射为 QEMU 启动命令行参数。
2. 超过 30 种处理器架构
支持 x86_64、ARM64、RISC-V 等 30+ 架构。在配置层,QEMUConstant.swift 中定义了完整的QEMUArchitecture枚举与各架构可用的机器类型;UTMQemuConfiguration+Arguments.swift 负责将这些选择翻译成-machine、-cpu等参数。
3. VGA 图形:SPICE + QXL
UTM 使用 SPICE 前端协议与 QEMU 通信,其优势在于比 VNC 更能胜任 USB 转发、多显示器,以及利用 guest 内 SPICE agent 实现剪贴板共享和分辨率动态调整。仓库中的 UTMSpiceIO 将 CocoaSpice(SPICE GTK 的 Cocoa/Objective-C 绑定)接入 UTM,并负责把 SPICE 的 Pixman 帧缓冲桥接到 Metal 纹理,最终由 MetalKit 渲染上屏。
4. 文本终端模式
除图形模式外,UTM 支持纯文本终端模式(通过 SPICE 串口通道),并集成了 SwiftTerm 终端组件(见下文许可证章节),适合运行无需图形界面的系统或进行串口调试。
5. USB 设备支持
iOS 与 macOS 端均支持 USB 设备透传。iOS 侧由 UTMUSBManager.swift 管理 USB 设备枚举与连接;macOS 侧还有工具栏级 USB 菜单(VMToolbarUSBMenuView.swift)。
6. 基于 QEMU TCG 的 JIT 加速
在无硬件虚拟化可用时,UTM 依赖 QEMU TCG(Tiny Code Generator)进行 JIT 动态代码生成。参数层面,UTMQemuConfiguration+Arguments.swift 在未启用 Hypervisor 时会生成-accel tcg,并根据配置附加thread=multi、tb-size=(JIT 翻译缓存大小,默认取内存的 1/4)、split-wx=on(无 JIT 权限时启用镜像映射)等参数。
7. 原生 UI 与设备端直接管理
UI 针对 macOS 11+ 与 iOS 11+ 使用原生 API 设计,支持直接在设备上创建、配置、运行虚拟机。所有虚拟机以.utm包形式存储,配置为 PLIST 格式(QEMU 后端对应UTMQemuConfiguration,Apple 后端对应UTMAppleConfiguration),通过Codable协议序列化。运行时管理则通过 QMP(QEMU Machine Protocol,基于 JSON over socket)完成,包括暂停/恢复、快照、鼠标/触控板切换、挂载可移动磁盘等(见 Architecture.md)。
三、macOS 专属:硬件级虚拟化
除了 QEMU 纯软件模拟,macOS 版还提供两项硬件加速能力:
1. Hypervisor.framework 加速
macOS 上 QEMU 支持hvf加速器,实现同架构虚拟化(x86 → x86 或 ARM64 → ARM64)。该框架在 iOS 上不可用。在 UTMQemuConfiguration+Arguments.swift 中可以看到,当启用 Hypervisor 时会生成-accel hvf,并根据需要附加tso=on(x86 上为兼容旧软件启用总存储序)与ipa-granule-size=0x1000(配合 Vulkan 支持)。
2. Virtualization.framework 运行 macOS 客户机
在 macOS 12+ 的 Apple Silicon Mac 上,UTM 可通过 Apple 的Virtualization.framework直接启动 macOS 客户机。对应的后端是 UTMAppleVirtualMachine.swift,其源码明确标注@available(iOS, unavailable)——该后端仅限 macOS。它的能力矩阵与 QEMU 后端不同(见 UTMAppleVirtualMachine.swift):支持恢复模式与截屏,但不支持进程级强杀、快照、临时模式和远程会话;配置则使用独立的UTMAppleConfiguration(SwiftCodable直接序列化,而非 QEMU 后端的NSDictionary包装)。
四、UTM SE:无需越狱的 JIT-less 版本
UTM/QEMU 为了最佳性能需要动态代码生成(JIT)。而 iOS 上的 JIT 要么需要越狱设备,要么依赖特定 iOS 版本的漏洞绕过。为此项目提供UTM SE("slow edition",慢速版):
- 技术方案:使用threaded interpreter(线程化解释器,TCTI)替代 JIT,其性能优于传统解释器但仍慢于 JIT;这一技术路线与 iOS 上的 iSH 项目动态执行思路类似;
- 分发方式:UTM SE 不需要越狱或任何 JIT 绕过方案,可以作为普通应用侧载安装(sideload);
- 架构裁剪:为优化构建时间与安装包体积,UTM SE 仅包含 ARM、PPC、RISC-V 与 x86 四类架构(均含 32/64 位变体)。
这一裁剪在源码中同样有据可查:QEMUConstant.swift 的WITH_QEMU_TCI编译分支中,QEMUArchitecture.isHidden仅放行aarch64、i386、m68k、ppc、ppc64、riscv64、x86_64,其余架构在 TCI 构建下对用户隐藏。iOS 开发文档中的预编译依赖产物表(见 Documentation/iOSDevelopment.md)也区分了普通版(ios-arm64)与 SE 版(ios-tci-arm64)对应的 sysroot。
五、安装与获取
- iOS:UTM (SE) 通过 getutm.app 分发,可侧载安装;
- macOS:通过 mac.getutm.app 获取正式版 DMG。
(官方安装渠道详见 README.ru.md。)若需从源码自行构建,请参考下文开发章节。
六、开发与构建指南
UTM 提供完整的开发文档:Documentation/MacDevelopment.md 与 Documentation/iOSDevelopment.md,仓库内scripts/目录集中了全部构建打包脚本。
1. 获取源码
UTM 依赖大量 submodule,必须递归克隆:
git clone --recursive <仓库地址>若已非递归克隆,可事后补齐:
git submodule update --init --recursive2. 依赖准备(两种方式)
方式一:使用预编译 sysroot(推荐):从 CI 构建产物中下载Sysroot-*工件,解压到仓库根目录即可。iOS 端按目标平台选择对应 sysroot:例如 Apple Silicon 真机用ios-arm64(SE 版为ios-tci-arm64),Intel 模拟器用ios_simulator-x86_64,visionOS 及其 SE 版、模拟器各有对应工件(详见 Documentation/iOSDevelopment.md 中的对照表)。
方式二:自行构建依赖(进阶):强烈建议在全新的 macOS 虚拟机中操作,因为部分依赖会错误地使用/usr/local/lib,且本机安装的libusb、gawk、cmake等包会破坏构建。步骤为:
- 安装 Xcode 命令行工具与 Homebrew;
- 安装构建前置依赖:
brew install bison pkg-config gettext glib-utils libgpg-error nasm meson pip3 install six pyparsing注意必须将
bison加入$PATH:export PATH=/usr/local/opt/bison/bin:/opt/homebrew/opt/bison/bin:$PATH - 执行依赖构建脚本(
ARCH为arm64或x86_64):./scripts/build_dependencies.sh -p macos -a ARCHiOS 端则使用
-p PLATFORM -a ARCHITECTURE,其中PLATFORM与ARCHITECTURE取自上文 sysroot 表的对应项(例如ios_simulator-tci+x86_64)。
需要制作通用二进制(universal binary)时,分别对arm64与x86_64构建后执行:
./scripts/pack_dependencies.sh . macos arm64 x86_64若正在开发 QEMU 并希望传入自定义源码路径,可给build_dependencies.sh加-q PATH_TO_QEMU_SOURCE参数(注意需使用 UTM 兼容的 QEMU fork)。
3. 命令行构建
macOS:
./scripts/build_utm.sh -t TEAMID -k macosx -s macOS -a ARCH -o /path/to/output/directoryARCH可取x86_64、arm64或(带引号)"arm64 x86_64"以生成通用二进制;TEAMID可选,仅在签名时需要。产物为未签名的.xcarchive。
iOS(运行./scripts/build_utm.sh可查看全部选项):
./scripts/build_utm.sh -k iphoneos -s iOS -a arm64 -o /path/to/output/directory把iOS换成iOS-SE即构建 UTM SE;把iphoneos换成xros则构建 visionOS 版本。
4. 打包与签名
脚本产物必须先重新签名才能使用。
macOS使用 scripts/package_mac.sh:
- 未签名包(缺少 USB 与网络桥接等能力):
./scripts/package_mac.sh unsigned /path/to/UTM.xcarchive /path/to/output生成
UTM.dmg,可安装到/Applications; - Developer ID 签名包(需付费开发者账号,以及带 Hypervisor 权限的 UTM、QEMUHelper、QEMULauncher 三个 provisioning profile):
./scripts/package_mac.sh developer-id /path/to/UTM.xcarchive /path/to/output TEAM_ID PROFILE_UUID HELPER_PROFILE_UUID LAUNCHER_PROFILE_UUID - Mac App Store 包(需 Apple Distribution 与 Mac App Distribution 证书):
./scripts/package_mac.sh app-store /path/to/UTM.xcarchive /path/to/output TEAM_ID PROFILE_UUID HELPER_PROFILE_UUID LAUNCHER_PROFILE_UUID
iOS使用 scripts/package.sh:
- 正式签名 IPA(需要带
get-task-allow权限的 Development 签名证书,而非 Distribution 证书):./scripts/package.sh signedipa /path/to/UTM.xcarchive /path/to/output TEAM_ID PROFILE_UUID免费开发者账号签名的应用 7 天过期,需每周重签;
- 未签名 IPA(可用 AltStore 或越狱设备的 AppSync Unified 安装):
./scripts/package.sh ipa /path/to/UTM.xcarchive /path/to/output - DEB 包(供 Cydia/Sileo 配合 AppSync Unified 安装):
./scripts/package.sh deb /path/to/UTM.xcarchive /path/to/output
5. Xcode 开发
Xcode 默认构建未签名版本(缺少 USB 与网络桥接能力)。如需完整能力,复制 CodeSigning.xcconfig.sample 为CodeSigning.xcconfig并填写 Team ID、Bundle ID 等;macOS 端需设置DEVELOPER_ACCOUNT_VM_ACCESS = YES,iOS 端付费账号设置DEVELOPER_ACCOUNT_PAID = YES以自动申请增大内存限制的 entitlement。
一个实用的调试提示:由于 macOS 系统 bug,在调试器挂载状态下启动虚拟机可能崩溃,建议先以调试器分离状态启动 UTM 与虚拟机,再通过 Debug → Attach to Process 附加调试器;此外 iOS 端 JIT 需要在调试器下启动(Tethered Launch,参见 Documentation/TetheredLaunch.md)。
七、许可证与第三方组件
- UTM 主体以宽松的Apache 2.0许可证分发;
- 但项目使用若干 (L)GPL 组件:大部分为动态链接,不过gstreamer 插件为静态链接,且部分代码直接取自 QEMU——计划再分发 UTM 时必须留意这些许可限制;
- 前端还依赖以下 MIT/BSD 许可组件:IQKeyboardManager、SwiftTerm、ZIP Foundation、InAppSettingsKit;
- 部分图标来自 Flaticon / Freepik,CI 托管由 MacStadium 提供。
八、结语:从 README 到源码的对照
纵观整个仓库,README 中每一句能力描述背后都有具体实现:-accel hvf与-accel tcg的参数生成逻辑在 UTMQemuConfiguration+Arguments.swift、TCI 架构裁剪在 QEMUConstant.swift、双后端能力差异在 Services 目录、构建打包流程在 scripts 目录。对开发者而言,这条“文档 → 配置 → 引擎”的链路,正是深入理解 UTM——乃至 QEMU 在 Darwin 平台落地方式——的最佳入口。
【免费下载链接】UTMVirtual machines for iOS and macOS项目地址: https://gitcode.com/gh_mirrors/ut/UTM
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考