Windows 95 es un sistema operativo de múltiples hilos que corre en el nivel de privilegio más alto, el anillo 0. Todos los programas de aplicaciones corren en el anillo 3, el nivel de menos privilegio.Como tales, los programas de aplicación están restringidos en lo que ellos pueden hacer al sistema. No pueden usar las instrucciones privilegiadas del CPU, no pueden accerder directamente al puerto I/O ni nada por el estilo.
Indudablemente, debes estar familiarizado con los tres componentes mayores del sistema: gdi32, kernel32 and user32. Seguro piensas que estas piezas tan importantes de código deberían correr en el nivel de privilegio más alto, el anillo 0. Pero en realidad corren en el anillo 3, como todas las otras aplicaciones. Así que no tienen más privilegio que, por ejemplo, el calculador de Window o el juego minesweeper. El poder real del sistema está bajo el control del manejador de máquina virtual [Virtual Machine Manager = VMM] y de los controladores de dispositivo virtual [ virtual device drivers (VxD) ].
Nada de esto puede ocurrir si DOS no complica más el panorama. Duriante la época de Windows 3.x, había lotes de útiles programas DOS en el mercado. Windows 3.x tenía que ser capaz de correrlos al lado de los otros programas de Windows, sino esto ocasionaría un fracaso comercial.
Este dilema no es fácil de resolver. Los programas de DOS y los de Windows son drásticamente diferentes unos de otros. Los programas de DOS son MALOS en el sentido de que ellos piensan que se apropian de todo en el sistema: teclado, CPU, memoria, disco, etc. No saben como cooperar con otros programas, mientras que los programas de Windows (en es tiempo)cuentan con multitarea cooperativa, es decir, todos los programas de Windows deben poder ceder control a otros programas a través de GetMessage o PeekMessage.
La solución es correr cada programa DOS en una máquina virtual 8086 mientras que otros priogramas de Windows corren en otra máquina virtual llamada máquina virtual del sistema [ system virtual machine ]. Windows es responsable de dar tiempo al CPU a cada máquina virtual en una manera round-robin. Bajo Windows 3.x, los programas de Windows usan multitarea cooperativa pero las máquinas virtuales usan multitarea preventiva.
¿Qué es una máquina virtual? Una máquina virtual es una ficción creada sólo por el software. Una máquina virtual reacciona ante programas corriendo como una máquina real. Así que un programa no sabe que corre en una máquina virtual y no lo toma en cuenta. En la medida que la máquina virtual responda a los programas exactamente como una máquina real, puede ser tratada como si fuera algoreal.
Puedes pensar en la interface entre la máquina real y su software como un tipo de API. Esta API inusual consta de interrupciones, llamadas a BIOS, y puertos E/S. Si Windows puede de alguna manera emular perfectamente esta API, los programas que corran en la máquna virtual se comportarán exactamente como si corrieran en una máquina real.
Aquí es donde VMM y VxDs entran en escena. Para coordinar y supervisar las máquinas virtuales (VMs), Windows necesita un program dedicado a esa tarea. Ese programa es el Manejador de Máquina Virtual [Virtual Machine Manager].
Cómo ves, VMM es la primera VxD que es cargada en memoria. Crea el sistema de máquina virtual e inicializa otras VxDs. También provee numerosos servicios a esas VxDs.
El modo en que operan VMM y y las VxDs es diferente a cómo operan los programas reales. La mayoría de las veces, se mantienen dormidas. Mientras los programas de aplicación corren en el sistema, las VxDs no están activas. Serán despertadas cuando ocurra alguna interrupción/falata/evento que necesite su atención.
EL VMM no puede hacer entradas reiteradas, no es reiterante. Eso significa que las VxDs deben sincronizar sus accesos con los servicios VMM. Hay algunas situaciones en las cuales no es seguro llamar a los servicios del VMM tal como cuando una interrupción de hardware está siendo servida. Durante ese tiempo, el VMM no puede tolerar reiteración de entradas. Tú, como escritor de VxD debes ser extremadamente cuidadoso sobre lo que estás haciendo. Recuerda que no hay manera de que Windows se cuide por tí de los errores de tu código. Dependes totalmente de tí mismo en el anillo 0.
Se emplea VxD como abreviatura para Controlador de Dispositivo Virtual [Virtual Device Driver]. x es el placeholder para el nombre del dispositivo tal como controlador de teclado virtual, controlador virtual del ratón y así. VxDs son la clave para una virtualización satisfactoria del hardware. Recuerda que los programas de DOS piensan que ellos son propietarios de todo en el sistema. Cuando ellos corren en máquinas virtuales, Windows tiene que suministrarles soporte de entrada [stand-ins] hacia los dispositivos reales. VxDs son esos soportes de entrada. VxDs usualmente virtualizan algunos dispositivos de hardware. Así, por ejemplo, cuando un programa de DOS piensa que está interactuando con el teclado, es realmente el dispositivo de teclado virtual el que está trabajando con él. Una VxD usualmente toma el control del dispositivo de hardware real y maneja el reparto de los dispositivos entre VMs.
Sin embargo, no existe ninguna regla según la cial las VxD DEBAN estar asociadas con un dispositivo de hardware. Es verdad que las VxDs están diseñadas para virtualizar dispositivos de hardware pero también podemos tratar las VxDs como DLLs de anillo-0. Por ejemplo, si quieres algunos rasgos que sólo pueden ser alcanzados en anillo 0, puedes codificar una VxD que ejecute la tarea por tí. En este aspecto, puedes ver la VxD como una extensión de tu programa puesto que no virtualiza ningún dispositivo de hardware.
Antes de que avances más y comiences a crear tus propias VxDs, dejame acotar algo antes.
APIs
de Servicio: Una VxD, incluyendo VMM, usualmente exporta un conjunto
de funciones públicas que pueden ser llamadas por otras VxDs. Esas funciones
se llaman servicios VxD. El mecanismo que consiste en llamar a esos servicios
VxD es muy diferente al de las aplicaciones del anillo-3. Toda VxD que exporta
servicios VxD DEBE tener un número
de ID único. Puedes obtener tales IDs de Microsoft. El ID es un número
de 16-bit que identifica únicamente una VxD. Por ejemplo
Puedes ver que la VMM tiene el ID de 1, VPICD tiene ID de 3 y así. VMM usa este único ID para encontrar la VxD que exporta los servicios VxD solicitados. también puedes seleccionar el servicio que quieras llamar por su índice en la rama de la tabla de servicios. Cuando una VxD exporta servicios VxD, almacena las direcciones de los servicios en la tabla. VMM usará el índice suministrado para localizar la dirección del servicio deseado a partir de la tabla de servicios. Por ejemplo, si quieres llamar a GetVersion, el cual es el primer servicio, tienes que especificar 0 (el índice tiene base cero). El mecanismo real de llamar servicios VxD involucra int 20h. Tu código emite int 20h seguido por un valor dword que está compuesto del ID del dispositivo y del índice del servicio. Por ejemplo, si quieres llamar el servicio número 1 que es exportado por una VxD que tiene el ID de dispositivo de 000Dh, el código sería más o menos como el siguiente:
La palabra alta de la dword que sigue a la instrucción int 20h contiene el ID del dispositivo. La palabra [word] baja tiene índice de base cero debtro de la tabla de servicio.
Cuando es generada la instrucción int 20h, VMM gana el control y examina la dword que sigue inmediatamente la instrucción de la interrupción. Luego extrae el ID del dispositivo y lo usa para localizar la VxD y luego usa el índice del servicio para localizar la dirección del servicio deseado en esa VxD.
Como puedes imaginar, esta operación consume tiempo, ya que la VMM debe gastar tiempo en localizar VxD y la dirección del servicio deseado. Así que VMM trampea un poco. Después que la primera operación int 20h es llevada a cabo satisfactoriamente, VMM muerde el enlace. Por morder el enlace entendemos que VMM reemplaza la int 20h y la dword siguiente con la llamada directa al servicio. Así que el recorte int 20h de arriba debería ser transformado a:
Callbacks: las funciones callbacks o callback son funciones que existen en las VxD para ser llamadas por otras VxDs. No confundas entre callbacks y servicios VxD. Las callbacks no son públicas como los servicios. Son funciones privadas de las que una VxD da sus direcciones a otras VxDs en situaciones específicas. Por ejemplo, cuando una VxD está sirviendo una interrupción de hardware, como VMM no puede hacer entradas repetidas, la VxD no puede usar ninguno de los servicios VxD que pueden usar fallos de página. La VxD puede dar la dirección de una de sus propias funciones (callback) a VMM de manera que VMM pueda llamar la función cuando VMM pueda tolerar fallos de página. La VxD puede entonces proceder con su trabajo cuando su función callback es llamada. La idea callback no es única para las VxD. Muchas de las APIs de Windows también las usan. El mejor ejemplo posiblemente sea el procedimiento de ventana. Especificas la dirección del procedimiento de ventana en la estructura WNDCLASS o WNDCLASSEX y la pasas a Windows con la llamada a RegisterClass o RegisterClassEx. Windows llamará tu procedimiento de ventana cuando hayan mensajes para la ventana. Otro ejemplo es el procedimiento de gancho de Window. Tu aplicación da la dirección del procedimiento de gancho a Windows de manera que Windows la llame cuando ocurran los eventos en los que la aplicación está interesada.
Los tres métodos de arriba
son usados para la comunicación entre VxDs. También hay interfaces
para aplicacionees en V86, modo protegido y Win32s.
[Iczelion's Win32 Assembly Homepage]
n u M I T_o r's Programming Page
Este tutorial, original de Iczelion, ha sido traducido por: n u M I T_o r