大多数浏览器和
Developer App 均支持流媒体播放。
-
创建 macOS 或 Linux 虚拟机
了解如何利用 Virtualization 框架在您的 Mac 上快速创建虚拟机。我们将介绍如何在隔离环境中创建虚拟 Mac 并快速测试对您的 App 的更改。我们还将探索如何在 Apple 设计的芯片上安装并运行完整的 Linux 版本,分享如何利用 Rosetta 2 来运行 x86-64 Linux 二进制文件。
资源
相关视频
WWDC23
-
下载
大家好 欢迎来到虚拟化课程 这是我们今天的内容 我们将了解如何在 Apple 芯片上 运行 macOS 和 Linux 虚拟机 在本课程结束时 你将能够在自己的 Mac 上操作 这可能有些挑战性 但跟上课程 我们就能实现 以下是今天的内容安排 我们将首先介绍虚拟化技术概述 并了解如何使用 Virtualization 框架 构建虚拟机 然后将深入研究 macOS 我们将了解如何设置 Mac 虚拟机 并为它安装 macOS 最后 我们再来深入研究 Linux 我们将了解如何运行完整的 Linux 发行版 以及一些很酷的新特性 我们从概述开始 我们将首先介绍 支持虚拟化的技术栈 首先是硬件 Apple 芯片拥有能够实现 CPU 和内存虚拟化的特殊硬件 这表示你可以在单个 SoC 上 运行多个操作系统 然后 我们需要软件来利用这个硬件 这是内置于 macOS 内核中的 你不再需要编写内核扩展或者 KEXT 一切都是内置的 要在应用程序中使用这些功能 你可以使用 Hypervisor 框架 Hypervisor 框架是一个底层 API 允许你虚拟化 CPU 和内存 但由于它是一个低级框架 你需要编写虚拟环境的每一处细节 通常 我们想要运行完整的操作系统 因此更高级别的 API Virtualization 框架应运而生 Virtualization 框架能够创建虚拟机 在 Apple 芯片上运行 macOS 或在 Apple 芯片和 Intel 上运行 Linux 我们今天将集中讨论 Virtualization 框架 在使用 Virtualization 框架时 我们将处理两类对象 第一类是配置对象 它们定义了虚拟机的所有属性 第二类是虚拟机对象 它们抽象化了虚拟机 以及和它们的交互方式 我们先来看配置 配置代表着硬件 创建配置就像在 Apple Store 商店中 配置 Mac 一样 我们要定义需要多少 CPU 多少内存和什么样的设备 我们可以从一个简单的配置开始 添加一个显示器 用来看到内容 再加一个键盘 可以打字 添加一个触控板 就可以与 UI 交互 配置虚拟机就是这样 但由于我们处理的是虚拟机 所以我们将利用代码来完成 我们来看看如何通过 Swift 编写配置 定义硬件非常简单 我们从 VZVirtualMachineConfiguration 这个类型开始 这是所有配置的根对象 然后 我们定义机器应该有多少 CPU 这里我们给出 4 个 CPU 然后 我们设置需要多少内存 这里我们设置为 4GB 最后 我们要定义机器将拥有的设备 这里我们定义了单个存储设备 引导磁盘和一个定点设备 如鼠标 有很多可用的设备 你设置什么取决于你想解决的问题 现在我们了解了配置 它从 VZVirtualMachineConfiguration 开始 我们在上面添加 CPU 内存和设备 接下来 我们来研究虚拟机对象
配置好 Mac 下单之后 我们通过快递收到它 下面就可以拆箱并启动它了 但我们处理的是虚拟机 需要利用代码来完成 我们来看看如何通过 Swift 完成 首先 我们通过配置 创建 VZVirtualMachine 实例 VZVirtualMachine 抽象了 虚拟硬件实例 现在我们有了虚拟机 就可以对其进行操作了 例如在本例中 我们调用 start() 来启动它 我们经常想要与虚拟机交互 因此我们需要其它对象的协助 例如 如果我们想要展示虚拟显示器 可以使用 VZVirtualMachineView 类型的对象 我们先创建一个视图 然后将视图上的 virtualMachine 属性 设置为我们的虚拟机 这样就大功告成了 现在我们可以像使用任何 NSView 一样 使用 VZVirtualMachineView 我们可以将它集成到 App 中 以查看虚拟机的内容
总结一下 我们已经看过了配置 配置是从 VZVirtualMachineConfiguration 开始 我们从中定义 CPU 内存和设备 通过配置 我们创建一个虚拟机 并使用虚拟机对象 我们已经了解了 VZVirtualMachine 抽象了虚拟机本身 VZVirtualMachineView 显示内容 还有其它对象可以协助我们 使用虚拟机 我们已经了解到 该配置为定义虚拟机 提供了很大的灵活性 遗憾的是 没法在一节课涉及太多功能 在本节课中 我们会研究一些核心能力 其它的内容均在文档中 我希望大家查看一下 我们在概述中了解了如何构建虚拟机 现在来研究如何在其中运行 完整的操作系统 我们将从 macOS 开始 Virtualization 框架 在 Apple 芯片上支持 macOS 当我们在 Apple 芯片上 构建 Virtualization 框架时 我们同时开发了 macOS 和 Virtualization 框架 这使得 在虚拟机中运行 macOS 时 效率十分惊人 以下是我们将要了解的内容 首先 我们会研究如何 将虚拟机变成 Mac 虚拟机 然后 我们将研究 在 Mac 虚拟机上安装 macOS 的步骤 接下来 我们还将了解到 macOS 的 一些特殊设备 最后 我们将学习一个 非常重要的实例 在主机系统和 Mac 虚拟机之间 共享文件
我们先从配置开始 我们已经了解了如何搭建通用虚拟机 现在我们想添加一些特殊属性 让其成为 Mac 虚拟机 那么我们如何配置 Mac 虚拟机呢 首先 我们要定义一个特殊的平台 平台是一个对象 它拥有特定类型虚拟机的所有属性 Mac 虚拟机硬件有三个独特的属性 第一个是硬件模型 硬件模型决定了我们需要的 Mac 虚拟机的版本 其次是辅助存储器 它是系统使用的一种非易失性存储器 第三个是虚拟机标识符 它是代表机器的唯一数字 就像每台 Mac 都有 唯一的序列号一样 一旦我们有了平台 就有了所有这些硬件 但还差一点 那就是引导 macOS 的方法 为此 我们将使用一个 特殊的引导加载程序 macOS 引导加载程序 我们来看看 如何在在 Swift 中做到这一切 我们还是从最基本的开始 这段代码是我们在概述中见过的 然后我们创建一个 VZMacPlatformConfiguration 这是我们的虚拟 Mac 平台对象 我们需要一个 Mac 的硬件模型 这里我们使用之前保存的一个 在虚拟机中 辅助存储器 由本地文件系统上的某个文件支持 在这里 我们通过 文件 URL 来初始化辅助存储器 我们从之前保存的一个标识符中 初始化 VZMacMachineIdentifier 对于新的安装 我们还可以创建一个新的标识符 我们已经设置好了三个属性 平台已准备就绪 我们所要做的就是 在配置对象上设置它 得到了硬件 接下来我们要找方法来启动它 为此 我们使用 VZMacBootLoader 来设置引导加载程序 现在我们的机器已准备好启动了 到目前为止 我们所做的 是如何定义虚拟 Mac 以及启动它 但我们仍需要在上面安装软件 这就涉及到安装 安装 macOS 需要三个步骤 首先 我们需要下载一个 带有要安装的 macOS 版本的恢复映像 然后 我们需要创建一个 与 macOS 版本兼容的配置 最后 我们将在兼容的 虚拟机中安装我们的恢复映像 首先 我们需要下载一个恢复映像 你可以从开发者网站下载 但 Virtualization 也可以帮到我们 你可以调用 VZMacOSRestoreImage.latestSupported 为最新稳定版本的 macOS 获取 恢复映像对象 这个对象有我们可以用来 下载文件的 URL 属性 然后 我们希望创建一个 与我们下载的 macOS 版本兼容的虚拟机 这里 Virtualization 也可以帮到我们 我们可以向恢复映像对象询问配置要求 如果恢复映像可以在当前系统上运行 我们会得到一个可以列出需求的对象 从需求中 我们可以得到运行该版本的 macOS 所需的硬件模型 我们已经看过了如何恢复硬件模型 这就是我们如何获得新模型
需求中还包含两个有用的属性 该对象可以告诉我们运行 这个版本的 macOS 需要多少 CPU 和内存 最后 我们准备好开始安装了 我们先从配置中创建一个新的虚拟机 然后创建一个安装程序 安装程序有两个参数 我们创建的兼容虚拟机 和下载恢复映像的路径 现在我们只需调用安装即可 看 我们准备好运行 macOS 了 现在我们可以设置 一个虚拟 Mac 并安装 macOS 我们来看看 Mac 的一些特殊设备 第一个很酷的功能是 GPU 加速 我们创建了一个图像设备 将 GPU 功能 暴露给虚拟 Mac 的 这表示你可以在虚拟机中运行 Metal 并在 macOS 中获得出色的图形性能 我们来看看如何设置它
我们首先创建图形设备配置 在这里 我们将使用 VZMacGraphicsDeviceConfiguration 然后我们要给它一个显示器 我们通过定义其大小 和像素密度来设置显示器 现在我们的设备已经设置好了 像往常一样 我们在主配置对象上设置它 我们将它设置为虚拟机的图形设备
接下来 我们来了解 与 Mac 互动的新设备 在 macOS Ventura 中 我们将 Mac 触控板支持 添加到了虚拟 Mac 中 新的触控板支持 旋转 缩放等手势 这个新设备 采用 macOS 中新的驱动程序 所以要想使用它 在主机系统 和虚拟机中均需要 macOS 13 我们来看看如何设置 很简单 我们创建一个 VZMacTrackpadConfiguration 类型的新对象 然后将其设置为虚拟机上的定点设备 当我们在虚拟 Mac 中使用视图时 可以使用手势 最后 我们来研究一下 大多数人的常见用例 即在主机系统和虚拟机之间共享文件 在 macOS 12 中 我们推出了 Virtio 文件系统设备 在 Linux 上共享文件 在 macOS Ventura 中 我们增加了对 macOS 的支持 你可以选择 想要与虚拟机共享的文件夹 你在主机系统中所做的任何更改 都会立即反应在虚拟机中 反之亦然 我们来看看如何设置 首先 我们创建一个带有我们想要 共享的目录的 VZShareDirectory 然后我们创建一个共享对象 这里我们使用 VZSingleDirectoryShare 来共享单个目录 您也可以用 VZMultipleDirectoryShare 来共享多个目录 现在有了共享 我们需要创建一个设备 但我们将从一个特殊的东西开始 文件系统设备由标记标识 在 macOS Ventura 中 我们添加了一个特殊标记 告诉虚拟机自动装载这个设备 这里 我们使用这个特殊标记 即 macOSGuestAutomountTag 然后我们创建设备 并使用我们的特殊标记 我们从所配置的单个目录设置共享 最后 像往常一样 将设备添加到配置中 最后 我们一起在演示中 查看所有内容 我们从基本配置开始 我们有 VZVirtualMachineConfiguration 它包含 CPU 内存 键盘和磁盘 我们想要一个虚拟 Mac 因此 我们需要从设置平台开始 我们将使用上面定义的 createMacPlatform 来做到这一点 创建虚拟 Mac 的第二步是 引导加载程序 我们需要知道如何启动 macOS 的 引导加载程序 为此 我们将平台的 引导加载程序设置为 VZMacOSBootLoader 接下来 我们要设置设备 我们需要加速图形端口 因此 我们设置一个 VZMacGraphicsConfiguration 我们创建对象 定义显示大小和像素密度 并将其添加到配置中 然后 我们想使用新的触控板 我们所要做的就是将定点设备 设置为 VZMacTrackpadConfiguration 以上就是全部 现在 我们可以启动虚拟机了 但是我们最后再添加一些东西 我们已经看到了如何共享目录 我们来演示一遍 我们首先创建文件系统设备配置 这里 请注意 我们使用特殊标记 将它自动装载到 macOS 中 然后定义我们的共享 这里 使用文件系统上的 路径的单个目录共享 这里 我们将共享 正在编辑的这个项目
将设备添加到配置中 这样就完成了 一切就绪 我们来启动应用程序 因为我们配置了 MacGraphics 设备 VZVirtualMachineView 就会显示内容 这就是我们在窗口中所看到的内容 就是它 我们从头开始配置 macOS 我们可以看到共享目录 和此刻正在编辑的项目 最后 我们来看一下 Linux Virtualization 框架 早在 macOS Big Sur 中 就已支持 Linux 在 macOS Ventura 中 我们增加了一些非常酷的新特性 我们想和大家分享其中的一些
首先 我们将看到如何在虚拟机中 安装完整的未经修改的 Linux 发行版 然后我们将看到在 Linux 中 添加的显示界面的新设备 最后 我们将看看如何利用 Rosetta 2 在虚拟机中运行 Linux 二进制文件 我们从安装开始 如果我们想在实体机上安装 Linux 首先要下载自带安装程序的 ISO 文件 然后用 ISO 覆盖一个U盘 最后 我们将U盘插入电脑 然后启动 在处理虚拟机时 我们将采用相同的步骤 但我们将使用虚拟U盘 而不是实际U盘 我们来看看它是如何工作的 我们首先从下载的 ISO 文件路径 创建 URL 然后 我们从该文件创建一个 磁盘映像附件 磁盘映像附件代表我们可以 连接到设备上的一块存储 接下来 我们配置一个虚拟存储设备 这里 我们需要 USB 存储 所以我们使用 VZUSBMassStorageDeviceConfiguration 最后 一如既往地 我们在主配置中添加设备 这里 USB 设备出现在 另一个存储设备一旁 也就是我们安装 Linux 的主磁盘 现在我们有了 USB 驱动器 但我们需要启动方法 在 macOS Ventura 中 我们增加了对 EFI 的支持 EFI 是引导 ARM 和 Intel 硬件的行业标准 我们正在为虚拟机提供同样的支持 EFI 具有启动发现机制 能够发现 USB 驱动器上的安装程序 EFI 可以查看每个驱动器 以寻找可以启动的驱动器 它会识别出安装程序 并以此作为开始 安装程序会告诉 EFI 接下来使用什么驱动程序 安装完成后 EFI 就可以 启动 Linux 发行版了 我们来看看 如何在代码中设置 EFI 首先 我们创建一个 VZEFIBootLoader 类型的引导加载程序 EFI 需要非易失性存储器 来存储启动间的信息 这就是所谓的 EFI 可变存储器 有了虚拟机 我们可以通过文件系统上的 某个文件来支持这样的存储器 这里 我们重新创建一个 新的可变存储器 现在 EFI 准备好了 我们只需要在配置中将它设置为 引导加载程序 接下来 我们将研究 Linux 虚拟机的 新功能 图形 在 macOS Ventura 中 我们增加了 对 Virtio GPU 2D 的支持 Virtio GPU 2D 是一个半虚拟化的设备 允许 Linux 为宿主 macOS 提供界面 Linux 呈现内容 将渲染帧提供给 Virtualization 框架 以便可以显示它 你现在可以用 VZVirtualMachineView 在你的 App 中显示这些内容 就像在 macOS 上一样 我们来看看如何设置它
设备设置与我们设置 macOS 时所做的类似 我们首先创建一个 VZVirtioGraphicsDeviceConfiguration 我们需要定义虚拟显示器的大小 在 Virtio 术语中 虚拟显示器是一个 “scanout” 所以我们创建了一个 显示器大小的 scanout 最后 我们将新设备设置为 配置的图形设备 现在我们的虚拟机已经准备好 用 VZVirtualMachineView 来显示内容了 接下来 我们通过演示 来查看所有内容 我们从中断的地方开始 先删除 Mac 特有的代码 然后更改引导的磁盘 我们将路径从 Mac 驱动器 换为 Linux 驱动器 接下来 需要一个引导加载程序 我们用 VZEFIBootLoader 来设置 EFI 首先创建 EFI 引导加载程序对象 然后我们从它的文件中 加载可变存储器 最后 我们在配置中将 EFI 设置为引导加载程序 现在我们可以启动了 不过最好能显示 UI 让我们将 Virtio GPU 添加到配置中 只需创建一个 VZVirtioGraphicsDeviceConfiguration 类型的图形设备 然后我们用虚拟显示器的 大小定义 scanout 我们在配置上将 Virtio GPU 设置为 graphicsDevice 最后就是让鼠标工作 我们只需使用虚拟的 USB 屏幕坐标指示设备 在 Linux 中会出现一个鼠标 好了 这样我们就可以 运行这个项目了 EFI 可以查看磁盘 识别是否可以引导 然后 Linux 通过 Virtio GPU 设备 显示界面内容 我们可以用鼠标与 Linux 交互 最重要的是 我们来看看如何 在 Linux 中使用 Rosetta 2 技术 对于许多人来说 我们喜欢在 Mac 上开发服务 但一旦我们的工作就绪 我们创建的二进制文件 可能需要在 x86 服务器上运行 x86 指令模拟在这方面做得很好 但我们可以做得更好 在 macOS Ventura 中 我们将 Rosetta 2 的强大功能 引入到 Linux 二进制中
Rosetta 2 所做的是在虚拟机中 转译 Linux x86-64 二进制 这表示你可以运行你喜欢的 ARM Linux 发行版 它的 x86-64 App 可以通过 Rosetta 运行 而且很快 这和我们在 Mac 上使用的技术 是一样的 这意味着我们拥有惊人的性能 让我们看看如何使用它 首先 我们需要让 Linux 可以访问 Rosetta 为此 我们使用了与 macOS 相同的文件共享技术 我们使用了一种特殊的对象 而非共享文件夹 也就是 VZLinuxRosettaDirectoryShare 然后我们创建一个共享设备 并设置 Rosetta 目录共享 最后 我们像往常一样 在配置上设置我们的设备 现在我们的虚拟机可以 使用 Rosetta 了 接下来 让我们看看 Linux 如何利用它
在 Linux 中 我们首先 在文件系统中装载共享目录 我们从 Linux 中看到的是可以 转译应用程序的 Rosetta 二进制文件 然后 我们可以使用 update-binfmts 告诉系统使用 Rosetta 处理任何 x86-64 二进制文件 不要担心记不住这个命令 这些全都在文档中 现在 Linux 已经准备就绪 Rosetta 会转译每一个 启动运行的 x86-64 二进制文件
在结束 Linux 部分之前 我们来进行一个大汇总 这里 我们重新安装了一个 完整的 Linux 发行版 我们可以用 Virtio GPU 2D 来显示它的界面 在虚拟机中 我们通过 Rosetta 运行了一个 PHP 服务器 我们可以从 macOS 主机与它连接
我们已经看到 创建虚拟机从未如此简单 利用 Virtualization 框架 你只需要写几行代码 就可以运行虚拟机 我们还看到 虚拟机 在 macOS 上的速度非常快 为了更进一步了解虚拟化 请大家查看代码示例和文档 我和我们的团队迫不及待地 想看到你们如何利用这项技术
-
-
4:11 - Running the virtual machine
let virtualMachine = VZVirtualMachine(configuration: configuration) try await virtualMachine.start()
-
4:33 - Showing the virtual machine’s display
let virtualMachineView = VZVirtualMachineView() virtualMachineView.virtualMachine = virtualMachine
-
7:43 - Start from the base
var configuration = VZVirtualMachineConfiguration() configuration.cpuCount = 4 configuration.memorySize = (4 * 1024 * 1024 * 1024) as UInt64 configuration.storageDevices = [newBlockDevice()] configuration.pointingDevices = [newPointingDevice()]
-
7:47 - Set up the platform
let platform = VZMacPlatformConfiguration() let hardwareModel = VZMacHardwareModel(dataRepresentation: savedHardwareModel) platform.hardwareModel = hardwareModel! let auxiliaryStorage = VZMacAuxiliaryStorage(contentsOf: auxiliaryStorageURL) platform.auxiliaryStorage = auxiliaryStorage let machineIdentifier = VZMacMachineIdentifier(dataRepresentation: savedIdentifier) platform.machineIdentifier = machineIdentifier! configuration.platform = platform
-
8:31 - Boot loader
configuration.bootLoader = VZMacOSBootLoader()
-
9:16 - 1. Getting an image
let restoreImage = try await VZMacOSRestoreImage.latestSupported try await download(restoreImage.url)
-
9:29 - 2. Create a compatible configuration
let requirements = restoreImage.mostFeaturefulSupportedConfiguration guard let requirements = requirements else { // No compatible configuration. return } platform.hardwareModel = requirements.hardwareModel configuration.cpuCount = requirements.minimumSupportedCPUCount configuration.memorySize = requirements.minimumSupportedMemorySize
-
10:10 - 3. Install macOS
let virtualMachine = VZVirtualMachine(configuration: configuration) let installer = VZMacOSInstaller(virtualMachine: virtualMachine, restoringFromImageAt: imageURL) try await installer.install()
-
10:58 - Setting up GPU acceleration
let graphicsConfiguration = VZMacGraphicsDeviceConfiguration() graphicsConfiguration.displays = [ VZMacGraphicsDisplayConfiguration(widthInPixels: 1920, heightInPixels: 1200, pixelsPerInch: 80) ] configuration.graphicsDevices = [graphicsConfiguration]
-
11:48 - Setting up the Mac trackpad
let trackpad = VZMacTrackpadConfiguration() configuration.pointingDevices = [trackpad]
-
12:33 - Share a folder
let sharedDirectory = VZSharedDirectory(url: directoryURL, readOnly: false) let share = VZSingleDirectoryShare(directory: sharedDirectory) let tag = VZVirtioFileSystemDeviceConfiguration.macOSGuestAutomountTag let sharingDevice = VZVirtioFileSystemDeviceConfiguration(tag: tag) sharingDevice.share = share configuration.directorySharingDevices = [sharingDevice]
-
16:10 - Setting up USB Mass Storage device configuration
let diskImageURL = URL(fileURLWithPath: "linux.iso") let attachment = try! VZDiskImageStorageDeviceAttachment(url: diskImageURL, readOnly: true) let usbDeviceConfiguration = VZUSBMassStorageDeviceConfiguration(attachment: attachment) configuration.storageDevices = [usbDeviceConfiguration, createBlockDevice()]
-
17:27 - Booting Linux
let efi = VZEFIBootLoader() efi.variableStore = VZEFIVariableStore(creatingVariableStoreAt: storeURL, options: []) configuration.bootLoader = efi
-
18:24 - Setting up Virtio graphics
let virtioGPU = VZVirtioGraphicsDeviceConfiguration() virtioGPU.scanouts = [ VZVirtioGraphicsScanoutConfiguration(widthInPixels: 1280, heightInPixels: 720) ] configuration.graphicsDevices = [virtioGPU]
-
21:02 - Setting up Rosetta
let rosettaDirectoryShare = try! VZLinuxRosettaDirectoryShare() let directorySharingDevice = VZVirtioFileSystemDeviceConfiguration(tag: "RosettaShare") directorySharingDevice.share = rosettaDirectoryShare configuration.directorySharingDevices = [directorySharingDevice]
-
21:37 - Setting up Linux
mount -t virtiofs RosettaShare /mnt/Rosetta sudo /usr/sbin/update-binfmts --install rosetta /mnt/Rosetta/rosetta \ --magic "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00" \ --mask "\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff" \ --credentials yes --preserve no --fix-binary yes
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。