O VirtualizationService
gerencia várias VMs convidadas, protegidas ou não, executadas em um sistema Android, principalmente gerenciando instâncias do crosvm.
O VirtualizationService
expõe uma API AIDL, que 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
. Enquanto houver
pelo menos uma referência ao objeto IVirtualMachine
, a VM vai continuar
em execução, a menos que falhe ou seja encerrada por conta própria. Se todas as referências ao objeto
IVirtualMachine
forem descartadas antes do encerramento da VM, o
VirtualizationService
vai encerrar a VM automaticamente. Esse processo implica que, se o cliente que iniciou a VM for encerrado pelo eliminador de memória insuficiente, 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. O 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 transmite a eles os descritores de arquivo das imagens que a
VM precisa. Em seguida, VirtualizationService
monitora o processo filho para saber quando ele
é encerrado e notificar os clientes restantes.
Pacotes de VM
O crosvm oferece duas maneiras diferentes de inicializar uma VM: com um kernel e um initrd ou com um carregador de inicialização. Em qualquer caso, um número arbitrário de imagens de disco também pode ser fornecido, 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 arquivo.
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, o
VirtualizationService
garante que os números de descritores de arquivo herdados pelo
crosvm sejam os mesmos usados pelo VirtualizationService
na criação das imagens compostas. A imagem de disco composta usa nomes de arquivo
no formato /proc/self/fd/N
para representar cada arquivo de partição.
Para pVMs do Microdroid, o AVF inclui um carregador de inicialização, que carrega o kernel de uma partição de uma imagem de disco composto, seguindo o fluxo padrão de inicialização verificada do Android.
Sockets de VM (vsock)
A interface principal para comunicação entre pVMs é vsock, uma interface de soquete virtio padrão. 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 pode ser reciclado
quando a VM é encerrada e todos os identificadores de vinculação IVirtualMachine
para a VM
são 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, veja os registros dela e encerre a VM. Com o comando vm
ou outras interfaces fornecidas pelo AVF, uma VM pode ser iniciada no modo
depurável (FULL) ou não depurável (NONE). Com uma VM depurável, é possível
ver registros no nível do SO, acessar o shell ADB e capturar um despejo de falha ou a carga útil do app.
Recomendamos usar uma VM não depurável em produção. Para mais informações sobre
a ferramenta de linha de comando e outras interfaces de depuração fornecidas pelo AVF, consulte
debug/README.md.