La implementación de la máquina virtual es un kernel para el kernel.
En un sistema operativo típico, hay código de aplicación (también conocido como "userland") y código de kernel . Utilizan el mismo conjunto de instrucciones; sin embargo, la CPU sabe, en cualquier momento, si está ejecutando la aplicación o el código del kernel. Cuando el código de la aplicación intenta ejecutar algunos códigos de operación que acceden al hardware (los códigos de operación in
y out
para x86), la CPU atrapa : salta temporalmente al código del kernel (la dirección de ese código es registrado en una tabla específica). El código del kernel decide qué hacer con el acceso (otorgarlo, modificarlo, detener el proceso de la aplicación ...). Si el código del kernel decide otorgar el acceso, o el kernel lo bloquea pero pretende haberlo realizado, entonces el código de la aplicación puede creer que podría acceder al hardware directamente.
Del mismo modo, cuando el código de la aplicación lee o escribe datos en la memoria, utiliza una abstracción de la memoria: un espacio de direcciones virtual que se asigna a la memoria física (o no ...) a través de la MMU . La MMU usa tablas que el kernel llena (y, por supuesto, el kernel se cuida de no hacer que estas tablas formen parte del espacio de direcciones visible desde el código de la aplicación). De esta manera, la aplicación está en un mundo mágico donde está sola en un gran espacio de direcciones, mientras que en realidad hay varias aplicaciones que se ejecutan simultáneamente, que no se pueden ver.
Una máquina virtual usa la misma estructura, un nivel más arriba. Cuando el kernel accede al hardware o a la MMU, en realidad está bajo el control de la implementación de la máquina virtual (el hipervisor ) que atrapa accesos no deseados.
Los detalles varían bastante. La distinción principal es si el kernel es consciente de que se ejecuta en una máquina virtual o no. Con Xen , el núcleo está al tanto; sabe que está bajo el control de una deidad superior (el hipervisor) y no intenta acceder directamente al hardware; en cambio, pregunta muy bien a través de una interfaz dedicada. Con VirtualBox , el núcleo no está al tanto; el sistema operativo invitado cree que se ejecuta en verdadero hardware, y la máquina virtual trabaja arduamente para mantener la ilusión.
Se pueden hacer otras diferencias en los medios por los cuales se aplica la virtualización (es decir, cómo el hipervisor puede atrapar el código del kernel). Los procesadores x86 recientes ofrecen algún soporte específico con opcodes dedicado . Los procesadores x86 más antiguos, en modo de 32 bits, pueden usar los diversos remanentes de los mecanismos de protección más antiguos (registros de segmentos y los cuatro "anillos", en su mayoría) (estos se han eliminado del modo de 64 bits, por lo que la máquina virtual de 64 bits debe utilizar AMD-V / VT-x). Otras técnicas incluyen emular cada código de operación virtualizado (para la totalidad de la máquina emulada, o partes de ella), posiblemente con una traducción más o menos dinámica (también conocida como compilación JIT), aas QEMU lo hace en situaciones de CPU cruzada.
Hay toda una parafernalia de términos sobre el tema (virtualización, paravirtualización, emulación, simulación, hipervisor ...) que no es completamente consensual y, a menudo, bastante bizantina. Algunos lectores que se aferran a algunas doctrinas específicas de la terminología probablemente se hayan sentido algo irritados por la forma sencilla en que uso los términos.