Puntos Básicos del Controlador de Dispositivo Dispositivo ( Virtual Device Driver )

En esta serie de tutoriales, asumo que tú, el lector, estás familiarizado con las operaciones del modo protegido del Intel 80x86 tales como el modo virtual, paginación, GDT, LDT, IDT. Si no sabes nada sobre esto, lee la documentación sobre Intel primero http://developer.intel.com/design/pentium/manuals/

Contenido:

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].

Manejador de Máquina Virtual [Virtual Machine Manager]

VMM es un programa de 32-bit en modo protegido. Su responsabilidad primordial es erigir y mantener el marco que soporta máquinas virtuales. Como tal, la VMM es responsable de crear, correr, y terminar VMs. VMM es uno de los muchos sistemas de VxDs almacenados en VMM32.VXD en tu carpeta de sistema. También es una VxD pero puede ser considerada como el supervisor de otras VxDs. Examinemos la secuencia de inicialización de Windows 95
  1. io.sys esa cargado en memoria
  2. config.sys y autoexec.bat son procesados
  3. win.com es llamado
  4. win.com corre VMM32.VXD que es realmente un simple archivo EXE de DOS.
  5. VMM32.VXD carga VMM dentro de la memoria extendida usando el controlador XMS
  6. VMM se inicializa a sí mismo y a otros controladores de dispositivos virtuales por defecto.
  7. VMM conmuta la máquina a modo protegido y crea el sistema de máquina virtual
  8. El Dispositivo de Shell Virtual [Virtual Shell Device], el cual es cargado de último, inicia Windows en el sistema VM al correr a krnl386.exe
  9. krnl386.exe carga los otros archivos, culminando en el shell de Windows 95.

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.

Controlador de Dispositivo Virtual [Virtual Device Driver]

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.

Hay dos tipos de VxD bajo Windows 95 Las VxDs estáticas son esas VxDs que son cargadas durante la inicialización del sistema y se mantienen cargadas hasta que el sistema se cierra. Este tipo de VxD data de los días de Windows 3.x. Las VxDs dinámicas son disponibles para Windows 9x sólamente. Las VxDs dinámicas pueden ser cargadas/descargadas cuando sea necesario. Muchas de ellas son VxDs que controlan dispositivos Plug and Play que son cargados por el Manejador de Configuración [Configuration Manager] y el Supervisor de Entrada y Salida [Input Output Supervisor]. También puedes cargar/descargar VxDs dinámicas desde tus aplicaciones win32.

Communicación entre VxDs

Las VxDs, incluyendo VMM, se communican entre sí a través de tres mecanismos: Mensajes de Control: VMM envía mensajes de control de sistema a TODAS las VxDs cargadas en el sistema cuando algo interesante ocurre. En este aspecto, los mensajes de control son como los mensajes de ventanas da las aplicaciones del anillo 3 de Windows. Toda VxD tiene una función que recibe y trata con mensajes de control llamada procedimiento de control de dispositivo [device control procedure]. Hay unos 50 mensajes de control de sistema. La razón por la que no hay muchos mensajes de control esd que frecuentemente hay muchas VxDs cargadas en el sistema y cada una de ellas obtiene un quiebre [crack] en cada mensaje de control, si hay muchos mensajes de control, el sistema hará un alto. Así que deberías encontrar sólo los mensajes realmente importantes relativos a VMs tales como cuando se crea o destruye una VM. Además de los mensajes de control del sistema, una VxD puede definir sus propios mensajes de control hechos a lña medida [custom] que puede usar para comunicarse con otras VxDs que la entienden.

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:

Este truco trabaja porque int 20h+dword toma 6 bytes, que es exactamente lo mismo que la instrucción call dword ptr. Así que las subsecuentes llamadas son eficientes. Este método tiene sus pro y sus contras. El lado bueno es que reduce el trabajo del cargador de VMM y VxD porque no tiene que fijar TODAS las llamadas de servicios de VxDs en el tiempo de carga. Las llamadas que nunca son ejecutadas se mantendrán sin modificación. El lado no tan bueno es que hace la descarga de VxD imposible. Como el VMM fija las llamadas con la dirección actual de los servicios VxD, las VxDs que proveen esos servicios no pueden descargarse. No hay mecanismo para librarse de los mordiscos a los enlaces. El corolario de esto es que las VxDs dinámicas no son convenientes como proveedoras de servicios VxD.

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.


Index

Next

[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