Serviço de virtualização

O VirtualizationService gerencia várias VMs de convidados, protegidas ou não, executadas em um sistema Android, principalmente gerenciando instâncias do crosvm. VirtualizationService expõe uma API AIDL, que os serviços ou apps do sistema podem usar para iniciar, monitorar e interromper VMs. Para usar VirtualizationService, execute virtmgr diretamente ou importe javalib ou rustlib, que executa virtmgr como um processo filho.

Ciclo de vida da VM

O acesso a uma VM é rastreado pelo objeto IVirtualMachine. Contanto que haja pelo menos uma referência ao objeto IVirtualMachine, a VM vai continuar em execução, a menos que ela falhe ou seja encerrada por conta própria. Se todas as referências ao objeto IVirtualMachine forem descartadas antes que a VM seja encerrada, o VirtualizationService vai encerrar a VM automaticamente. Esse processo implica que, se o cliente que iniciou a VM for desligado pelo low memória killer, a VM também será encerrada, evitando vazamentos de recursos.

Cada VM é gerenciada pela própria instância do crosvm, que VirtualizationService gerencia em nome do cliente. VirtualizationService em virtmgr inicia esses processos filhos do crosvm conforme necessário com recursos globais alocados, incluindo o CID concedido por VirtualizationServiceInternal em virtualizationservice, e os transmite aos descritores de arquivo das imagens de que a VM precisa. O VirtualizationService monitora o processo filho para quando ele morre, para que possa notificar os clientes restantes.

Empacotamento de VMs

O crosvm oferece suporte a duas maneiras diferentes de inicializar uma VM: um kernel e um initrd ou um carregador de inicialização. Em ambos os casos, também é possível fornecer um número arbitrário de imagens de disco, que pode ser uma imagem bruta ou um composto de várias partições. As várias imagens são fornecidas pelo cliente como descritores de arquivos.

O VirtualizationService cria imagens de disco compostas sob demanda. Esse processo é necessário porque o arquivo de disco composto se refere internamente aos vários arquivos de imagem de partição que compõem o disco, que são transmitidos pelo cliente e podem não ser acessíveis diretamente pelo crosvm. Para contornar esse problema, VirtualizationService garante que os números de descritor de arquivo herdados por crosvm sejam os mesmos que os números de descritor de arquivo que VirtualizationService usou na criação das imagens compostas. A imagem de disco composta usa nomes de arquivos no formato /proc/self/fd/N para representar cada arquivo de partição.

Para pVMs Microdroid, o AVF inclui um carregador de inicialização, que carrega o kernel de uma partição de uma imagem de disco composta, seguindo o fluxo padrão de inicialização verificada do Android.

Soquetes de VM (vsock)

A interface principal para comunicação entre pVMs é o vsock, uma interface padrão de soquete virtio. Cada VM é identificada por um identificador de contexto de 32 bits (CID), que é análogo a um endereço IP, que VirtualizationServiceInternal atribui à VM quando VirtualizationService cria a VM e pode expor serviços em qualquer número de porta escolhido pela VM. O CID é exclusivo enquanto a VM está em execução, mas o valor do CID pode ser reciclado quando a VM é encerrada e todos os identificadores de vinculação IVirtualMachine para a VM foram descartados.

Interface de depuração

O comando vm é fornecido para fins de depuração. Esse comando permite que um desenvolvedor inicie uma VM no shell, acesse os registros dela e encerre a VM. Com o comando vm ou outras interfaces fornecidas pelo AVF, uma VM pode ser iniciada no modo depuração (FULL) ou não depurável (NONE). Com uma VM depurável, é possível ver registros no nível do SO, acessar o shell do adb e capturar o crash-dump ou o payload do app. É recomendável usar uma VM não depurável na produção. Para saber mais sobre a ferramenta de linha de comando e outras interfaces de depuração fornecidas pelo AVF, consulte debug/README.md.