VirtualizationService

VirtualizationService 主要通过管理 crosvm 的实例来管理多个在 Android 系统上运行的客户机虚拟机(无论是否受保护)。VirtualizationService 公开了一个 AIDL API,系统服务或应用可以使用该 API 来启动、监控和停止虚拟机。如需使用 VirtualizationService,请直接执行 virtmgr,或导入将 virtmgr 作为子进程执行的 javalibrustlib

虚拟机生命周期

对虚拟机的访问权限由 IVirtualMachine 对象跟踪。只要至少有一个对 IVirtualMachine 对象的引用,虚拟机就会继续运行(除非它自行崩溃或关停)。如果在虚拟机关停之前丢弃了对 IVirtualMachine 对象的所有引用,那么 VirtualizationService 会自动关停虚拟机。此过程意味着,如果启动虚拟机的客户端因低内存终止守护进程而关闭,那么该虚拟机也会关停,从而防止资源泄露。

每个虚拟机都由自己的 crosvm 实例管理,VirtualizationService 反过来代表客户端管理该实例。virtmgr 中的 VirtualizationService 会根据需要使用分配的全局资源(包括 virtualizationservice 中的 VirtualizationServiceInternal 授予的 CID)启动这些 crosvm 子进程,并向其传递文件描述符用于提供虚拟机所需的映像。然后,VirtualizationService 会监控子进程的终止时间,以便相应地通知所有剩余的客户端。

虚拟机打包

crosvm 支持两种不同的虚拟机启动方式:提供内核和 initrd,或者提供引导加载程序。此外,无论是哪种情况,都可以提供任意数量的磁盘映像,这些映像可以是原始映像,也可以是多个分区的组合。各种映像是由客户端作为文件描述符提供。

VirtualizationService 会按需构建复合磁盘映像。此过程很有必要,因为复合磁盘文件在内部引用构成磁盘的各种分区映像文件,这些映像文件由客户端传递,并可能无法直接通过 crosvm 访问。为了解决此问题,VirtualizationService 会确保由 crosvm 继承的文件描述符编号与 VirtualizationService 用于创建复合映像的文件描述符编号相同。复合磁盘映像使用 /proc/self/fd/N 形式的文件名来表示每个分区文件。

对于 Microdroid pVM,AVF 会包含一个引导加载程序,该引导加载程序会按照标准 Android 启动时验证流程,从复合磁盘映像的分区中加载内核。

虚拟机套接字 (vsock)

pVM 之间进行通信的主要接口是 vsock,这是一个标准的 Virtio 套接字接口。每个虚拟机都由一个 32 位上下文标识符 (CID)(类似于 IP 地址)标识,在 VirtualizationService 创建虚拟机时,VirtualizationServiceInternal 会为虚拟机分配此标识符,并可在虚拟机选择的任何端口号上公开服务。在虚拟机运行时,此 CID 具有唯一性,但当虚拟机终止且虚拟机的所有 IVirtualMachine binder 句柄均被舍弃时,CID 值可以被回收。

调试界面

为调试目的提供了 vm 命令。此命令可让开发者从 shell 启动虚拟机,查看其日志,并终止虚拟机。借助 vm 命令或 AVF 提供的其他接口,虚拟机可以在可调试 (FULL) 或不可调试 (NONE) 模式下启动。借助可调试的虚拟机,您可以查看操作系统级日志、访问 adb shell,以及捕获崩溃转储或应用载荷。建议在生产环境中使用不可调试的虚拟机。如需详细了解命令行工具以及 AVF 提供的其他调试接口,请参阅 debug/README.md