Story Transcript
Device Driver de Disco para un Sistema de Virtualización basado en Minix Abstract El sistema operativo de microkernel Minix [1] brinda un entorno adecuado para desarrollos experimentales, incluso para incorporarle funciones de hipervisor y poder gestionar así Máquinas Virtuales (del inglés VMs). Mhyper es un sistema operativo basado en Minix que implementa estas facilidades y que incorpora un hipervisor para administrar máquinas virtuales El presente trabajo presenta aspectos relacionados al diseño y desarrollo de un device driver de disco para que las VMs puedan utilizar archivos regulares como imágenes de disco virtuales.. Palabras Clave Minix, Sistema Operativo, hipervisor, Máquinas Virtuales, device driver, disco rígido.
Introducción La virtualización [2] consiste en un software que emula al hardware y puede ejecutar programas como si fuera una computadora real. Dicho software se denomina hipervisor. Esta tecnología permite que una sola computadora contenga múltiples máquinas virtuales (VMs), denominadas huéspedes (en inglés Guests). En particular, la paravirtualización es un tipo de virtualización en la cual el código fuente de los huéspedes es modificado de manera que en lugar de ejecutar instrucciones sensibles que provocan excepciones que son atrapadas por el hipervisor, realicen explícitamente llamadas al hipervisor (hypervisor calls). Minix es un OS basado en microkernel y estratificado, desarrollado por Andrew Tanenbaum con fines académicos. En Minix, todos los procesos y tareas son aislados y se comunican a través de mensajes. El microkernel se encarga de planificar procesos, de las transiciones entre estados, de atender interrupciones, excepciones y fallos, y de la transferencia de mensajes. Este nivel de independencia de los procesos y las tareas permiten desarrollar multiples alternativas al momento de crear drivers o servidores.
En este sentido, el microkernel de Minix posee un mecanismo similar al de la paravirtualización. Se puede afirmar que este actúa como hipervisor paravirtualizado de una única VM. El propósito de este artículo es presentar los aspectos relacionados al diseño, implementación y evaluación de un device driver de disco virtual para un sistema de virtualización basado en Minix, denominado MHyper[3]. MHyper puede dar soporte a múltiples VMs con Minix como huesped. Elementos del Trabajo y metodología Contexto Una máquina virtual debe contar con las siguientes características:
Duplicado: Debería comportarse de forma idéntica a la máquina real, excepto por la existencia de menos recursos disponibles y diferencias de temporización al tratar con dispositivos; Aislamiento: Se pueden ejecutar varias VMs sin interferencias. El aislamiento debe ser: o De rendimiento: El rendimiento de una VM no debe afectar al de otra VM; o De fallo: Un fallo de una VM no debe provocar ningún efecto en las demás; o De seguridad: No debe ser posible acceder a ningún recurso de una VM desde otra; Eficiencia: La VM debería ejecutarse a una velocidad cercana a la del HW real.
Existen varios tipos de virtualización: Hipervisor tipo I (full virtualization): El monitor se ejecuta directamente sobre el hardware en modo kernel y los huéspedes sobre el monitor en modo usuario;
Hipervisor tipo II (indirecto): El monitor se ejecuta sobre un OS en modo usuario y los huéspedes sobre el monitor; Paravirtualización: Consiste en modificar el código fuente del OS huésped para que en vez de ejecutar instrucciones sensibles realicen llamadas al hipervisor. De esta forma se logra un rendimiento cercano a la ejecución en las máquinas reales.
Minix es un sistema operativo de tipo cliente/servidor basado en microkernel. En su versión 3 los procesos se dividen en 4 capas, como se muestra en la figura 1. Los procesos de las capas 2, 3 y 4 se ejecutan en modo usuario y comprenden las siguientes categorías: Procesos de usuarios; Procesos servidores; Device Drivers o tasks.
creó una herramienta de administración para cargar, iniciar, detener, reanudar y terminar las VMs utilizando las llamadas al sistema atendidas por VMM. Las demás VMs son versiones de Minix que no ejecutan su propio kernel, pero poseen todos las demás tareas, drivers y servidores. Para mantener el aislamiento de seguridad, recursos y fallos, el espacio de direcciones de memoria asignado a una VM no puede ser accedido por ninguna otra, incluyendo la VM0. El Process Manager (PM) de la VM0 que es responsable de gestionar memoria no tiene bajo su gestión el rango de direcciones de memoria de una VM hasta que ésta termina. Además, la SYSTASK mantiene el control del rango del espacio de direcciones de cada VM para poder controlar que las llamadas al kernel solicitadas por un proceso operan dentro del área de memoria asignado a su VM (como por ejemplo la copia de bloques de memoria entre procesos). La arquitectura de procesos de MHyper se muestra en la figura 2.
Figura 1. Estructura de Minix 3 Debido a la similitud mencionada anteriormente entre Minix y un sistema de paravirtualización, el proyecto MHyper busca adaptar a Minix para convertir a la tarea del sistema (SYSTASK) de Minix en un hipervisor paravirtualizado para múltiples VMs. MHyper posee una arquitectura similar a la de los contenedores de Linux [4]. La VM0 es una VM privilegiada que permite administrar las demás VMs. Al iniciarse, posee todos los recursos del sistema, por lo que si no se inicia ninguna VM trabaja de igual forma que un Minix normal. Fuera del espacio del microkernel, se añadió un nuevo servidor para administrar VMs llamado Virtual Machine Manager (VMM), exclusivo de la VM0. También se
Figura 2. Arquitectura de Mhyper MHyper ya se encuentra desarrollado y es completamente funcional, pero la VM0 y las distintas VMs invitadas utilizan cada una particiones de disco diferentes o unidades de díscos rígidos diferentes. Más allá que cada VM posee su propio device driver de disco que administra la lectura y escritura en la unidad de almacenamiento asignada, que Mhyper es un sistema paravirtualizado donde la escritura real del
disco duro está a cargo del hypervisor. Es una característica común de los sistemas de virtualización comerciales la utilización de archivos como si fuesen unidades de disco que son utilizadas por las VMs invitadas. Mhyper brinda múltiples posibilidades de virtualización, y en éste artículo describimos los detalles de diseño e implementación de un driver de disco que utiliza archivos regulares como unidades de discos rígidos. Conceptos preliminares Antes de introducirnos más profundamente en la descripción de la solución e implementación es necesario repasar las facilidades requeridas para desarrollar 3 funciones de importancia. IPC La comunicación entre procesos (IPC) es una función básica de los sistemas operativos que le permite a los procesos comunicarse entre sí. La IPC provee un mecanismo que permite a los procesos comunicarse y sincronizarse entre sí, normalmente a través de un sistema de bajo nivel de paso de mensajes que ofrece la red subyacente. Estas primitivas IPC fueron modificados para soportar aislamiento de IPC, procesos Virtual, procesos Proxies (o representantes) y procesos promiscuos. Las nuevas primitivas de IPC que se incorporaron el microkernel pueden ser utilizadas por procesos proxies y por procesos de promiscuos (por lo tanto, ejecutando en VM0). En Minix las primitivas de IPC podrían ser utilizados en cualquier VM como send(), receive(), sendrec() y notify(). Los endpoints (que se utilizan para identificar a un proceso) y números de procesos utilizados como argumentos de estas funciones no necesitan distinguir entre procesos regulares, procesos virtuales o procesos promiscuos. La existencia de este tipo de procesos es enmascarada para todos los procesos que se ejecutan en máquinas virtuales invitadas (distintas de VM0).
Para el desarrollo del Device Driver se utilizó la facilidad de proceso Proxy y proceso Virtual que ofrece Mhyper. Los procesos virtuales existen pero no se ejecutan dentro de una VM y pueden ser destinos del envío de mensajes por parte de otros procesos ordinarios ejecutando dentro de la misma VM. Mhyper se hace cargo de interceptar las transferencias de mensajes destinadas al proceso virtual, el emisor es bloqueado y se le notifica al proceso Proxy de la VM que hay un mensaje esperando en el proceso virtual. Un proceso Proxy se ejecuta en VM0 y es encargado de crear y cargar una imagen de una VM. Al ejecutar en VM0 tiene la posibilidad de realizar llamadas al sistema POSIX tradicionales. Cada VM tiene un proceso Proxy en VM0 que recibirá los mensajes dirigidos a los procesos virtuales de la VM que representa. El proceso Proxy atiende las solicitudes y luego le responde a los procesos solicitantes pero en nombre del destinatario de la petición (el proceso virtual). Una ventaja de este enfoque es que un proxy puede utilizar todos los recursos ofrecidos por el sistema operativo de Minix en VM0 (todas llamadas al sistema) o por cualquiera de sus servidores o tareas (task calls). Su principal desventaja es que requiere de una transferencia de mensaje adicional por cada petición que perjudica el tiempo de respuesta y que el servidor Proxy atiende secuencialmente las peticiones de los todos los device drivers que representa. El desarrollo de este trabajo se efocara en programar a este Proxy como el device driver de disco utilizando un archivo de imagen.Mhyper pone a disposición de los programadores de sistema un nuevo conjunto de primitivas de IPC que pueden ser utilizadas solo por procesos ejecutando en VM0 tales como los procesos Proxies y estas se denominan sendas(), recvas() notifyas().
Sendas() Esta primitiva de IPC permite que un proceso proxy de una VMx ejecutando en VM0 envíe un mensaje a un proceso regular ejecutando en VMx tal como si fuese enviado por un proceso virtual de VMx. El proceso Proxy de VMx con endpoint caller_ep dentro VM0 envía un mensaje a otro proceso en VMx con endpoint dst_ep como si fuese el proceso virtual con endpoint virtual_ep dentro de VMx. int sendas(dst_ep, &msg, virtual_ep) donde: dst_ep: endpoint destino. msg: direccion del buffer. virtual_ep: endpoint del proceso virtual de VMx que será el remitente del mensaje. Si la operación es correcta retorna OK. De lo contrario retorna un código < 1, lo que india un error
Se envía un mensaje desde el buffer msg a un destino con endpoint dst_ep en virtual_ep como remitente del mensaje. El kernel controla que el proceso que usa sendas() sea el proceso Proxy de VMx. El destino debe ser un proceso regular dentro de VMx (el destino no puede ser un extremo del proceso Virtual o un extremo promiscuo proceso dentro de un VMx ≠ VM0). El virtual_ep debe ser un proceso Virtual dentro de VMx. Recvas() Esta primitiva de IPC permite que proceso Proxy de una VMx ejecutando VM0 reciba un mensaje proveniente de proceso regular de VMx destinado a proceso virtual en VMx.
un en un un
int recvas(src_ep, &msg, virtual_ep) donde: src_ep: endpoint origen. Debe ser un endpoint válido dentro VMx, ANY para recibir un mensaje de cualquier origen. msg: dirección del buffer del mesaje. virtual_ep: el destinatario del mensaje debe ser un proceso virtual de la VMx. Si la operación es correcta retorna OK. De lo contrario retorna un código < 1, lo que india un error
Esta primitiva recibe un mensaje de un origen especificado con endpoint src_ep en VMx envió a un Virtual proceso con endpoint virtual_ep dentro de VMx. Sólo puede ser utilizado por el proceso Proxy de VMx. Notifyas() Esta primitiva de IPC permite que un proceso proxy de una VMx ejecutando en VM0 envíe un mensaje de notificación (no bloqueante) a un proceso regular ejecutando en VMx tal como si fuese enviado por un proceso virtual de VMx. El proceso Proxy de VMx con endpoint caller_ep dentro VM0 envía un mensaje NOTIFY_MESSAGE a un proceso dentro de VMx con endpoint dst_ep como si fuese el proceso virtual con endpoint virtual_ep dentro de VMx. int notifyas(dst_ep, virtual_ep) donde: dst_ep: endpoint del destinarario. virtual_ep: endpoint del proceso como mensaje del remitente. Si la operación es correcta retorna OK. De lo contrario retorna un código < 1, lo que india un error
Solo el proceso Proxy de la VMx ejecutando en VM0 puede ejecutar esta primitiva de IPC. El destino debe ser un proceso regular dentro de VMx (el destino no puede ser un extremo del proceso Virtual o un extremo promiscuo proceso dentro de un VMx ≠ VM0). El virtual_ep debe ser un proceso Virtual dentro de VMx. Proxy Para el desarrollo del Proxy se deben dejar bien en claro la diferencia que existe en te los procesos proxy y los procesos virtuales. Los procesos virtuales son aquellos que se ejecutan exclusivamente dentro de una VM específica sin conocimiento de la existencia de las demás VM. Cada instancia de estos procesos pertenece a una VM. Una VM en este entorno puede considerarse como una forma de agrupar y el confinamiento de los procesos. Cada proceso de modo de usuario
pertenece a una VM. La virtualización se hace cargo de interceptar las peticiones de llamada de sistema procedentes de procesos de modo de usuario y redirige a los servidores de VM. Se los conoce por virtuales dado que no existen fuera del entorno dela VM que los creo y los ejecuta. Los procesos proxy son aquellos que crea las VM pero se ejecutan en el entorno de las VM0 de esta forma las VM tiene la posibilidad de realizar operaciones sin la necesitada de depender de que el hipervisor. Cada VM debe tener un proceso proxy en VM0 que reciben todos los mensajes dirigidos a los driver de la VM. Los procesos proxy realizan las solicitudes sobre el driver Real y luego responder a procesos de solicitante. Una ventaja de este enfoque es que un proxy puede utilizar todos los recursos ofrecidos por el sistema operativo de Minix en VM0 (todas llamadas al sistema) o por cualquiera de sus servidores o tareas (llamadas tareas). Los inconvenientes son que requiere a una transferencia de mensaje adicional aumentando el tiempo de respuesta y que el servidor proxy proceso secuencialmente las peticiones de los conductores. Bajo este concepto de procesos proxy, el mismo cargador de máquinas virtuales ( el loadvmimg[3] ) se podría clasificar como un proxy de la máquina virtual que está cargando. Este proceso de la VM0 una vez finalizada la carga en memoria de la VM pasa a ser el servidor de proxy que comunica la VM con los distintos driver reales (figura 4). Solución Para cumplir con las condiciones de aislamiento exigidos por la virtualización se propone utilizar un Proxy que actué como intermediario entre el device driver de disco de las VMs y el sistema de archivos del Sistema Operativo subyacente (VM0) (Figura 3). Cada máquina virtual posee su propia instancia del Proxy donde se establece que unidad de disco rígido utilizará.
Figura 3. Mhyper con Proxy Al iniciar una VMs el MHyper utiliza un archivo de configuración donde están configuradaslas distintas VM. Es en este archivo donde se configura el tipo de devide driver que va a utilizar la VM. machine CONAIISI { size 64; boot_prog "/usr/src/proxy/loadvmimg"; boot_image "/boot/MYMINIX.img"; boot_bitmap 0xFFFFFFFF; process at_wini VIRTUAL_PROC_TYPE EXEC_LOADED TASK_LEVEL EXEC_NTFY; device at_wini "/usr/MYMINIX.dsk"; };
En el caso del device driver de disco (at_wini) se le específica a la VM que dicho driver será virtual (VIRTUAL_PROC_TYPE), es decir que este no se encargara por sí mismo de las lectura y escrituras en el disco, sino que se harán por medio del Proxy. En este archivo también se especifica cual será el archivo que la VMs va a utilizar como disco virtual (/usr/MYMINIX.dsk). Una de las versatilidades que tenemos al implementar este device driver utilizando un Proxy es que no se requiere que el disco sea un disco físico, el mismo también puede ser un disco virtual, una partición, un archivo o incluso un disco alojado en otra equipo accedido mediante comunicación de red.
Implementación Para poder usar el device driver de disco rígido creó un nuevo driver para el disco. Este recibe como configuración inicial cual será el archivo que se va a utilizar como disco virtual para la VMx. Una petición realizada por el File System de la VMx (FSx) (dentro de VMx) destinada al controlador de dispositivo virtual de disco (AT_WINI de VMx) es notificada por el microkernel al Proxy de la VMx. Al recibir esa notificación el Proxy invoca a recvas() para recibir este mensaje de FSx. Posteriormente, el proxy realiza las operaciones solicitadas en el disco asignado usando llamadas del sistema estándar de POSIX (fread(), fopen(), fwrite(), fseek(), fclose()) y responde al FSx utilizando sendas().Cuando el programa de encargado de cargar la imagen booteable de la VMx (en el ejemplo: loadvmimg) termina de cargarla, inicia su bucle principal llamado do_proxy(). Figura 4. Distribución de memoria de las VM Una vez iniciada la VM, esta trabaja como si tuviera su propio disco, solo que cuando solicita una operación, esta es capturada por el Proxy y redirección al archivo correspondiente utilizando operaciones de archivos estándares POSIX. Metodología de trabajo Para facilitar el desarrollo del device driver se optó por utilizar el software de virtualización VMware Workstation 12 donde se instaló el sistema operativo MHyper. Una vez creado y testeado el sistema operativo con el nuevo device driver en las máquina virtual de desarrollo se procederá a instalarlo en una máquina real donde se podrá evaluar su rendimiento Esta etapa aún no se llevó a cabo por dificultades que se presentaron con la compatibilidad de hardware propios de Minix y por lo tanto heredadas por Mhyper.
void do_proxy(int vmid){ int rcode, driver_nr; rcode = proxy_init(vmid); fl_vmid = vmid; while (true) { rcode = receive(ANY, &m); if(!rcode){ if(m_ptr->m_source == HARDWARE) { virtual_bm = (m_ptr)->NOTIFY_ARG; while(virtual_bm) { driver_nr = get_driver_nr(); if(driver_nr < 0) continue; rcode = (*driver_vec[driver_nr]) (driver_nr); fflush(log); }; } } } }
El Proxy espera por un mensaje de tipo NOTIFY_MESSAGE proveniente del kernel que le alerta que hay un mensaje destinado al proceso virtual de la VMx (device driver). La función get_driver_nr() retorna el número de controlador que fue el
destino de ese mensaje. Posteriormente, el Proxy llama a la función que le dará tratamiento a la petición para ese dispositivo; la función at_wini_driver() dará tratamiento a las peticiones de disco. La función del controlador correspondiente recibirá la solicitud destinada al proceso virtual (device driver de disco) utilizando recvas(). El Proxy responderá al solicitante utilizando sendas().
copiar los datos de un espacio de direcciones del solicitante al destinatario:
int at_wini_driver(int driver_nr) { if( driver_nr == NO_DRIVER) return(at_wini_init()); ..... rcode = recvas(ANY, mi_ptr, driver_nr); ..... switch(fl_rqst) { case DEV_OPEN: ..... break; case DEV_READ: ..... rcode = fread(devbuf, 1, bytes, fp_disc[dr_index]); .... break; case DEV_WRITE: ..... rcode = fwrite(devbuf, 1, bytes, fp_disc[dr_index]); .... break; } .... rcode = sendas(mi_ptr->m_source, mo_ptr, driver_nr);
sys_vcopy(): Como el espacio de dirección completo de una VM esta embebido en el segmento de datos del Proxy se puede hacer una copia de un bloque de datos entre espacios de direcciones de VM0. Sólo hay que convertir direcciones origen/destino de VMx en una dirección virtual proxy. Si VMx asigna memoria comienza en la dirección virtual del proxy VMx_start, la dirección virtual del buffer origen/destino en VMx es sd_addr_X, y dirección virtual del buffer que se refiere el espacio de direcciones del proxy es: sd_addr_proxy = VMx_start + sd_addr_X (Figura 5). Este problema se resuelve por la función rvirt_lvirt() que convierte la dirección virtual que se refiere a un proceso dentro de VMx en una dirección virtual referido al Proxy dentro VM0.
sys_vcopyvm(): Esta kernel call permite que el Proxy solicite al SYSTASK copiar un bloque de datos entre el espacio de direcciones del solicitante y del destinatario. Un espacio de direcciones debe ser sobre VM0 y otro sobre VMx o viceversa.
if( rcode) { return(rcode); } return(OK); }
Dentro de las operaciones que puede hacer una VM con este driver se destacan las dos más importantes que son DEV_READ y DEV_WHITE. Estas solicitudes van a dar tratamiento a los requerimientos de lectura y escritura sobre el disco virtual. Existen tres métodos (utilizadas por VM0) para
Figura 5. Conversión de dirección de VMx a Proxy memcpy(): Si el servidor proxy necesita copiar datos desde/hacia su propio espacio de dirección a/desde el espacio de direcciones de un proceso dentro de VMx, puede utilizar las funciones memcpy() sin llamar al SYSTASK para la conversión de dirección con el mismo método de sys_vcopy().
Resultados: A lo largo del todo el proyecto se realizaron un conjunto de pruebas estándares verificar el correcto funcionamiento del disco virtual, utilizando el entorno de desarrollo (Mhyper ejecutando sobre VMware No pudieron realizarse pruebas de rendimiento sobre una maquina real por problemas que se presentaron con el hardware disponible Para las pruebas se utilizó uno de los comandos más usados que es el .tar. Estas pruebas se realizaron con VMware 7.1.2 build-2780323 sobre Windows7 en una PC con AMD A6-3670 2.70 Ghz con 4Gbytes de RAM, se configuro una VM con 256 Mbytes de RAM y a la VM1 se le asignaron 64 Mbytes La ejecución de la operación tar generó un archivo de 49902592 bytes, cuyos tiempos de ejecución se muestran en la figura 6. VM Ware Minix VM Ware Mhyper VM0 VM Ware Mhyper VM1
TIEMPO [S]
551,91
91
91,16
TAR
Figura 6. Tiempos comparativos de creación de tar A pesar de que los tiempos de Minix y de Mhyper con VM0 son prácticamente los mismos se observa una importante diferencia con respecto al mismo proceso en la VM1. Esa pérdida de rendimiento era de esperar dado que no se accede al disco real sino que se accede al Proxy, luego al FS de VM0, luego al Driver de Disco de VM0 y que el número de mensajes es más del doble que el acceso directo al disco. Los resultados son los esperados y hemos logrado el objetivo de poder crear un Proxy que administre el disco rígido de las VM. Quedan pendientes más pruebas de rendimiento sobre hardware real y
analizar la posibilidad de optimizaciones para mejorar los tiempos de respuesta. Conclusiones y trabajos futuros: En este trabajo se presenta el diseño e implementación de un device driver de disco rígido virtual que utiliza archivos de imágenes de disco para el sistema de virtualización basado en Minix denominado Mhyper. El hecho de realizar el trabajo sobre un sistema operativo de microkernel y estratificado simplifica mucho las tareas de desarrollo y brinda una excelente ambiente para su modificación y experimentación. Los conocimientos adquiridos al trabajar con este sistema virtualización no se limitan solamente al mismo, sino que son un punto de partida para el aprendizaje de cuestiones relacionadas a la virtualización en general. Cabe destacar que la funcionabilidad del Proxy permite implementar device drivers para distintos tipos de dispositivos Como trabajo futuro y continuación de este se está desarrollando un device driver de disco virtual que se encuentra en un archivo de imagen de un Linux remoto mediante el protocolo de transferencias de mensajes de Minix. Referencias [1] Tanenbaum, A. S., Woodhull, A. (2006). Operating Systems: Design and Implementation- 3o edición. Prentice Hall. [2] Tanenbaum, A. S. (2009). Sistemas Operativos Modernos - 3o edición. Prentice Hall. [3] Pablo Pessolani, “Virtualization Extensions into a Microkernel based Operating System”. CONAIISI 2014 – San Luis. [4] LXC - Linux Containers https://linuxcontainers.org [7] MINIX 3 Documentation http://www.minix3.org/documentation/index.html