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.