Servizio di virtualizzazione

VirtualizationService gestisce più VM guest, protette o meno, in esecuzione su un sistema Android, principalmente tramite la gestione di istanze di crosvm. VirtualizationService espone un'API AIDL, che i servizi di sistema o le app possono utilizzare per avviare, monitorare e arrestare le VM. Per utilizzare VirtualizationService, esegui direttamente virtmgr o importa javalib o rustlib che esegue virtmgr come processo secondario.

Ciclo di vita di una VM

L'accesso a una VM è monitorato dall'oggetto IVirtualMachine. Finché esiste almeno un riferimento all'oggetto IVirtualMachine, la VM continua a funzionare (a meno che non si arresti in modo anomalo o non si arresti autonomamente). Se tutti i riferimenti all'oggetto IVirtualMachine vengono eliminati prima dell'arresto della VM, VirtualizationService arresta automaticamente la VM. Questo processo implica che se il client che ha avviato la VM viene arrestato dal programma di eliminazione a bassa memoria, viene arrestata anche la VM, impedendo così le perdite di risorse.

Ogni VM è gestita dalla propria istanza di crosvm, che VirtualizationService a sua volta gestisce per conto del cliente. VirtualizationService in virtmgr avvia questi processi secondari crosvm in base alle esigenze con risorse globali allocate, incluso il codice identificativo concesso da VirtualizationServiceInternal in virtualizationservice, e li connette ai descrittori file delle immagini di cui la VM ha bisogno. VirtualizationService monitora quindi il processo secondario quando termina, in modo da poter avvisare di conseguenza gli eventuali client rimanenti.

Imballaggio delle VM

crosvm supporta due diversi modi per avviare una VM: vengono forniti un kernel e un initrd o un bootloader. In entrambi i casi, è possibile fornire anche un numero arbitrario di immagini disco, che possono essere un'immagine non elaborata o un insieme di più partizioni. Le varie immagini vengono fornite dal client come descrittori file.

VirtualizationService crea immagini disco composito on demand. Questo processo è necessario perché il file del disco composito fa riferimento internamente ai vari file immagine di partizione che compongono il disco, che vengono passati dal client e potrebbero non essere accessibili direttamente da crosvm. Per aggirare il problema, VirtualizationService garantisce che i numeri dei descrittori file ereditati da crosvm siano gli stessi dei numeri dei descrittori file utilizzati da VirtualizationService per creare le immagini composite. L'immagine disco composita utilizza i nomi dei file nel formato /proc/self/fd/N per rappresentare ogni file della partizione.

Per le pVM Microdroid, AVF include un bootloader, che carica il kernel da una partizione di un'immagine del disco composito, seguendo il flusso di Avvio verificato standard di Android.

Socket VM (vsock)

L'interfaccia principale per la comunicazione tra le pVM è vsock, un'interfaccia socket virtio standard. Ogni VM è identificata da un identificatore di contesto (CID) a 32 bit, analogo a un indirizzo IP, che VirtualizationServiceInternal assegna alla VM quando VirtualizationService la crea e può esporre i servizi su qualsiasi numero di porta scelto dalla VM. L'ID cliente è univoco mentre la VM è in esecuzione, ma il valore dell'ID cliente può essere riutilizzato quando la VM viene terminata e tutti i handle del binder IVirtualMachine per la VM sono stati eliminati.

Interfaccia di debug

Il comando vm viene fornito a scopo di debug. Questo comando consente a uno sviluppatore di avviare una VM dalla shell, visualizzarne i log e terminarla. Con il comando vm o con altre interfacce fornite da AVF, una VM può essere avviata in modalità di debug (FULL) o non di debug (NONE). Con una VM di cui è possibile eseguire il debug, puoi visualizzare i log a livello di sistema operativo, accedere alla shell ADB e acquisire il dump in caso di arresto anomalo o il payload dell'app. È consigliabile utilizzare una VM non di debug in produzione. Per saperne di più sullo strumento a riga di comando e su altre interfacce di debug fornite da AVF, consulta debug/README.md.