Highlight
macOS Sonoma 的 Virtualization framework 新增可调整大小的显示器、VM 状态保存与恢复、网络块设备(NBD)存储、NVMe 控制器支持以及 Rosetta 2 缓存优化,让虚拟 Mac 和 Linux VM 更易用、更灵活、性能更高。
核心内容
以前用 Virtualization framework 跑虚拟机,显示器分辨率是固定的。窗口拉大,VM 画面不会跟着变,要么留黑边,要么得手动改分辨率。这对日常在虚拟 Mac 里工作的体验很不友好。
(01:19)macOS Sonoma 新增了 automaticallyReconfiguresDisplay 属性。打开后,VM 的显示分辨率会跟随窗口大小实时调整,空间利用率更高。
另一个痛点是 VM 的生命周期管理。以前关掉 VM 等于断电,所有未保存的工作状态都丢了。重新打开要冷启动,应用、文档、浏览标签全得重新打开。
(01:31)Sonoma 引入了保存和恢复机制。可以把运行中的 VM 完整序列化到磁盘文件,之后随时恢复到保存时的状态。这对备份工作进度、快速切换任务场景都很有用。
存储方面,以前磁盘镜像只能放在本地。现在支持通过网络块设备(NBD)协议挂载远程存储,让 VM 的磁盘可以放在远程服务器上。这对数据中心场景尤其有价值。
(12:04)Rosetta 2 在 Linux VM 中的性能也有提升。新增了翻译缓存守护进程,重复使用的 x86_64 代码无需重复翻译,编译和包安装等 exec 密集型任务会明显更快。
详细内容
可调整大小的显示器
(01:58)VZVirtualMachineView 新增了一个布尔属性 automaticallyReconfiguresDisplay。设为 true 后,调整窗口大小会自动通知 VM 调整分辨率。
let virtualMachineView = VZVirtualMachineView()
virtualMachineView.virtualMachine = virtualMachine
virtualMachineView.automaticallyReconfiguresDisplay = true
关键点:
VZVirtualMachineView是 Virtualization framework 提供的原生视图组件automaticallyReconfiguresDisplay默认值为false,保持原有固定分辨率行为- 设为
true后,VM 内部会收到显示配置变更事件,动态调整分辨率 - 虚拟 Mac 和 Linux VM 都支持此特性
保存与恢复 VM 状态
(04:20)保存前需要先暂停 VM,确保执行处于稳定状态:
// virtualMachine is a running VZVirtualMachine.
try await virtualMachine.pause()
let saveFileURL = URL(filePath: "SaveFile.vzvmsave", directoryHint: .notDirectory)
try await virtualMachine.saveMachineStateTo(url: saveFileURL)
关键点:
pause()将 VM 挂起,CPU 执行暂停saveMachineStateTo(url:)把完整的运行时状态写入指定文件- 外部资源(如磁盘镜像)需要单独复制备份
- 保存文件经过硬件加密,其他 Mac 或用户账户无法读取
(04:58)恢复时,从相同配置创建新的 VM 实例,然后加载保存文件:
let configuration = VZVirtualMachineConfiguration()
// Customize configuration.
let virtualMachine = VZVirtualMachine(configuration: configuration)
let saveFileURL = URL(filePath: "SaveFile.vzvmsave", directoryHint: .notDirectory)
try await virtualMachine.restoreMachineStateFrom(url: saveFileURL)
try await virtualMachine.resume()
关键点:
- 恢复前不要直接调用
start(),否则会冷启动 restoreMachineStateFrom(url:)加载保存的状态数据resume()恢复执行,VM 回到保存时的精确状态- 保存文件有版本号,格式不兼容时框架会返回特定错误码
网络块设备(NBD)存储
(09:28)Virtualization framework 实现了 NBD 协议的客户端。存储可以放在任意位置的 NBD 服务器上:
let url = URL(string: "nbd://localhost:10809/myDisk")!
let attachment = try VZNetworkBlockDeviceStorageDeviceAttachment(url: url)
let blockDevice = VZVirtioBlockDeviceConfiguration(attachment: attachment)
关键点:
VZNetworkBlockDeviceStorageDeviceAttachment是新的附件类型- URL 格式为
nbd://host:port/diskName - 可以与
VZVirtioBlockDeviceConfiguration或VZUSBMassStorageDeviceConfiguration搭配使用 - 对 VM 完全透明,VM 感知不到存储在远程
(10:02)网络连接可能中断,可以通过 delegate 监听状态变化:
let url = URL(string: "nbd://localhost:10809/myDisk")!
let attachment = try VZNetworkBlockDeviceStorageDeviceAttachment(url: url)
let delegate = NetworkBlockDeviceAttachmentDelegate()
attachment.delegate = delegate
let blockDevice = VZVirtioBlockDeviceConfiguration(attachment: attachment)
关键点:
- delegate 遵循
VZNetworkBlockDeviceStorageDeviceAttachmentDelegate协议 - 连接断开时可以暂停 VM 或尝试重连
- 自定义 I/O 逻辑(如特殊镜像格式或物理驱动器)可以在 NBD 服务器端实现
NVMe 控制器支持
(11:21)某些 Linux 内核没有 virtio 驱动,但通常有 NVMe 驱动。Sonoma 新增了对 NVMe 控制器的模拟支持:
let nvmeDevice = VZNVMExpressControllerDeviceConfiguration(attachment: attachment)
关键点:
VZNVMExpressControllerDeviceConfiguration是新的设备类型- 仅适用于 Linux VM,虚拟 Mac 仍推荐使用 virtio block
- 也支持 NBD 附件
Rosetta 2 缓存优化
(13:46)Rosetta 2 在 Linux VM 中新增了翻译缓存守护进程。需要配置通信通道并在 VM 内启动守护进程:
// 配置 Rosetta 2 运行时与缓存守护进程的通信通道
let rosettaConfiguration = VZRosettaDirectoryShare()
// 在 VM 内启动守护进程后,动态链接请求会转发到守护进程
// Rosetta 2 运行时直接从守护进程获取预翻译的二进制文件
关键点:
- 翻译结果缓存到磁盘,多个应用共享
- 避免重复翻译相同的库和可执行文件
- 对编译、包安装等 exec 密集型任务提升最明显
核心启发
-
做一个带快照功能的 VM 管理器
- 利用
saveMachineStateTo和restoreMachineStateFrom,在应用退出时自动保存 VM 状态,下次启动秒开 - 实现思路:监听应用生命周期事件,在
applicationWillTerminate中调用保存 API
- 利用
-
构建远程开发环境
- 用 NBD 把 VM 磁盘放在公司服务器或云主机上,本地 Mac 只跑计算
- 实现思路:搭建 NBD 服务器,配置
VZNetworkBlockDeviceStorageDeviceAttachment挂载远程磁盘
-
做一个 x86 Linux 兼容测试工具
- 利用 Rosetta 2 缓存优化,在 Apple Silicon Mac 上快速运行 x86_64 Linux 构建和测试
- 实现思路:创建 Linux VM,启用 Rosetta 2,配置共享文件夹挂载项目代码
-
自适应分辨率的虚拟桌面客户端
- 打开
automaticallyReconfiguresDisplay,让远程虚拟桌面始终填满本地窗口 - 实现思路:在
VZVirtualMachineView创建时设置属性,监听容器视图大小变化
- 打开
关联 Session
- Create macOS or Linux virtual machines — WWDC22 的 Virtualization framework 入门,适合先了解基础再深入本 session
- What’s new in Swift — 本 session 的 API 大量使用了 Swift async/await,了解最新 Swift 特性有助于更好使用这些 API
- Meet SwiftData — 如果你在 VM 管理应用中需要持久化配置和快照元数据,SwiftData 是理想选择
评论
GitHub Issues · utterances