Driver de Dispositif Virtuel, Elémentaire

(Virtual Device Driver Basics)




Dispositif = Matériel. (ex: le clavier la souris...)

Dans cette série de Tutorials, je présumerai que le lecteur soit déjà familier avec les opérations des processeurs Intel 80x86 à propos des modes protégés tels que le mode virtuel 8086, la pagination, GDT, LDT, IDT. Si vous ne savez pas de quoi je parle, lisez d'abord la documentation d'Intel à l'adresse http://developer.intel.com/design/pentium/manuals/

Contenu:

Windows 95 est un système d'exploitation multi-taches fonctionnant au niveau le plus haut (privilégié), le Ring 0. Toutes les applications normales donc les autres programmes possèdent un privilège de type Ring 3, c'est le niveau de moindre privilège. De cette manière, ces applications sont limitées dans ce qu'elles peuvent faire au système. Elles ne peuvent pas employer les instructions privilégiées du CPU, Ces programmes ne peuvent pas avoir directement accès au port d'entrée-sortie et cetera. Vous connaissez sans aucun doute ces trois composants du système: gdi32, kernel32 et user32. Vous pensiez vu leur importance qu'ils fonctionnaient en Ring 0. Et bien...en réalité, ils fonctionnent en Ring 3, comme toutes les autres applications. Ainsi ils n'ont pas plus de privilège que, disons, la calculette de Windows ou le jeu du démineur. En réalité, la puissance du système est dans le contrôle de l'administrateur de machine virtuelle (VMM) (virtual machine manager) et des Drivers de Dispositifs Virtuals (VxD) (virtual device drivers).
Tous ça n'aurait pas pu arriver si DOS n'avait pas rendu le tableau plus compliqué. Durant l'ère de Windows 3.x, il y a eu des tas de bons programmes sous DOS sur le marché. Windows 3.x a été capable de les faire fonctionner à côté d'autres programmes Windows normaux, sinon ça auraient été des échecs commercialement.
Ce dilemme n'a pas été facile à résoudre. Les programmes DOS et les programmes de Windows diffèrent résolument les uns des autres. Les programmes DOS sont NULS dans le sens qu'ils pensent êtres un tout unique dans le système : clavier, CPU, mémoire, disque etc. Ils ne savent pas comment coopérer avec d'autres programmes tandis que les programmes Windows (en ce temps-là) reposaient sur la multi-gestion coopérative, c'est-à-dire que chaque programme Windows devait rapporter le contrôle à d'autres programmes grâce à la fonction GetMessage ou PeekMessage.
La solution c'est de faire tourner chaque programme DOS dans une machine virtuelle 8086 tandis que tous les autres programmes de Windows tournent dans une autre machine virtuelle appelée system de machine virtuelle (system virtual machine). Windows est responsable de l'accès au CPU pendant un certain temps pour chaque machine virtuelle les unes après les autres. Ainsi sous Windows 3.x, les programmes Windows utilisent la multi-gestion coopérative tandis que les machines virtuelles utilisent la multi-gestion préventive.
Qu'est-ce qu'une machine virtuelle ? Une machine virtuelle est une machine fictive créée seulement par le logiciel. Une machine virtuelle réagit aux programmes qui sont en fonctionnement comme une machine réelle. Ainsi un programme sait qu'il tourne dans une machine virtuelle mais il ne s'en soucie pas. Puisque la machine virtuelle répond au programme exactement comme une machine réelle, alors elle peut être traité comme étant une chose réelle.
Vous pouvez vous représenter l'interface entre la machine réelle et son logiciel un peu comme une sorte d'API. Cet API peu commun consiste à intercepter, les appels du BIOS et des ports d'entrée-sortie. Si Windows peut d'une façon ou d'une autre parfaitement simuler cet API, alors les programmes tournant dans la machine virtuelle se comporteront exactement comme s'ils fonctionnaient dans la machine réelle.
c'est là qu'entrent en scène les VMM et les VxDs. Pour coordonner et surveiller des machines virtuelles (VMs), Windows a besoin d'un programme qui se consacre à cette tâche. Ce programme est le Manager de Machine Virtuelle.

Le Manager de Machine Virtuelle : (Virual Machine Manager)

VMM est un programme 32 bits en mode protégé. Sa responsabilité principale est d'ériger et d'entretenir la structure qui soutient des machines virtuelles. Comme tel, il est responsable de la création, du fonctionnement et de la fin des VMs (Machines Virtuelles). Le VMM (le Manager) est un des nombreux systèmes VxDs qui est stocké dans VMM32.VXD de votre répertoire System. C'est aussi un VxD mais il peut être considéré comme le 'maître surveillant', d'autres VxDs. Voyons plus en détails la séquence de Boot de Windows 95:
  1. io.sys est chargé en mémoire
  2. config.sys et autoexec.bat sont exécutés
  3. win.com est appelé
  4. win.com lance VMM32.VXD lequel est en fait un simple fichier EXE sous DOS.
  5. VMM32.VXD charge le VMM en mémoire étendue en utilisant le driver XMS
  6. VMM initialise lui-même d'autres 'virtual device drivers' par défaut.
  7. VMM met la machine en mode protégé et crée le 'système de machine virtuelle'
  8. (Virtual Shell Device) Le Dispositif Shell Virtuel, qui a été chargé précédemment, fait tourner Windows dans le système VM en lançant krnl386.exe
  9. krnl386.exe charge d'autres fichiers, pour en finir avec le shell de Windows 95.
Comme vous pouvez le voir, VMM est le premier VxD qui soit chargé en mémoire. Il crée le système de la machine virtuelle et initialise d'autre VxDs. Il fournit aussi de nombreux services à ces VxDs.
Le VMM (le manager de Machine virtuelle) et le mode d'opération des VxDs diffèrent de celui des programmes réels. Ils sont, la plupart du temps, inertes. Pendant que les applications tournent dans le système, ces VxDs ne sont pas actifs. Ils seront réveillés quand une quelconque interruption/faute/événement se produit et a besoin de leur attention.
Le VMM n'est pas le décideur. Ça signifie que les VxDs doivent synchroniser leurs accès aux services du VMM. Il y a quelques situations pour lesquelles il peut être dangereux d'appeler les services du VMM tel que lorsque une interruption matériel est en service. Pendant ce temps-là, le VMM ne peut pas tolérer un autre accès de la part d'un autre VxD. Vous en tant que concepteur de nouveaux VxDs devez être extrêmement prudents à ce que vous faites. Rappelez-vous qu'il n'y a personne pour s'occuper des erreurs de votre code à votre place. Vous êtes absolument seul dans le Ring 0. Ici vous êtes sur le fil du rasoir, il n'y aura personne pour vous dire ou non si vous faites des conneries.

Driver de Dispositif Virtuel: (Virtual Device Driver)

L'abréviation du 'Virtual Device Driver' est VxD. x est le placeholder pour le nom du dispositif utilisé, comme Virtual Keyboard Driver, ou Virtual Mouse Driver et cetera. Les VxDs sont les clefs de la réussite pour virtualiser le matériel. Souvenez-vous, les programmes sous DOS pensent qu'ils possèdent tout dans le système, qu'ils sont seuls sur la machine et que la souris le clavier et le reste sont directement et uniquement à leur service. Quand ils tournent sur des machines virtuelles, Windows doit leur fournir des remplaçants de dispositifs réels. C'est ça les VxDs, ce sont des remplaçants de souris, clavier… mais virtuels. Les VxDs d'habitude virtualisent quelques dispositifs matériel. Ainsi, par exemple, quand un programme DOS pense qu'il communique avec le clavier, en réalité c'est le dispositif virtuel du clavier qui travaille avec lui. Un VxD prend d'habitude le contrôle du dispositif (du matériel) réel et gère la division de ce dispositif entre plusieurs VMs.
(En fait votre ordinateur est divisé en plusieurs 'ordinateurs virtuels' ou 'Machines Virtuelles (VMs)'. Vous n'avez qu'un clavier mais pour que chaque Machine Virtuelle puisse l'utiliser, un VxD (un clavier virtuel) est calé entre chaque Machine Virtuelle et le vrai clavier physique. Le Manager de Machines Virtuelles (VMM) octroie un laps de temps machine à tour de rôle à chacune des Machines Virtuelles où un seul programme tourne dessus.)
Cependant, il n'y a aucune règle pour qu'un VxD DOIVENT forcément être associé à un dispositif de matériel précis. Il est vrai que les VxDs soient conçus pour virtualiser des dispositifs matériel (normalement réels) mais nous pouvons aussi considérer les VxDs comme étant des DLL de priorité Ring-0. Par exemple, si vous souhaitez utiliser quelques particularités qui ne peuvent seulement être réalisées qu'en Ring 0, vous pouvez coder un VxD qui exécute ce travail pour vous. À cet égard, vous pouvez vous représenter le VxD comme étant l'extension de votre programme puisque il virtualise un quelconque dispositif(Device) matériel.
Avant d'aller plus loin et d'essayer de créer vos propres VxDs, laissez-moi d'abord faire le point à propos de certaines choses sur eux. Il y a deux types de VxD sous Windows 95 Les VxDs Statiques sont ces VxDs qui sont chargés pendant le bootup (le démarrage) du système et reste chargé jusqu'à l'arrêt du système. Ce type de VxD provient des vieux jours de Windows 3.x. Les VxDs Dynamiques sont uniquement disponibles sous Windows 9x. Les VxDs Dynamiques peuvent être chargés/déchargés si nécessaires. La plupart d'entre eux sont des VxDs qui contrôlent les Plug and Play Devices (des périphériques qui sont automatiquement détectés par Windows au moment de leur installation). Ces VxDs là, sont chargés par le 'Manager de Configuration et le 'Superviseur d'Entrée/Sortie'. Vous pouvez aussi charger/décharger ces VxDs dynamiques pour vos applications win32.

Communication Entre les VxDs :

Les VxDs (Les Virtuals Devices, tels que le clavier virtuel) et le VMM (le Manager de Machine Virtuelle), communiquent entre eux de trois façons possibles : Les Messages de Control: Le VMM envoie des messages de contrôle au système vers TOUS les VxDs chargés dans le système quand certains événements intéressants se produisent. Dans ce cas précis, considérez que les messages de contrôle sont un peu comme de simples 'Messages de Fenêtres' en Ring-3 dans des applications Win32. Chaque VxD a une fonction qui reçoit et traite les messages de contrôle appelée device control procedure. Il y a un peu moins de 50 systèmes de 'Messages de Contrôle'. La raison pour qu'il n'y ait pas beaucoup de messages de contrôle c'est qu'il y a souvent beaucoup de VxDs chargés dans le système et que chacun d'entre eux obtient un accès dans chaque message de contrôle, s'il y a trop de messages de contrôle, le système rectifiera avec une halte. Ainsi vous trouverez seulement les messages vraiment importants liés aux VMs comme quand une VM (Machine Virtuelle) est créée, détruite ou autre. En plus du système de 'Messages de Contrôle', un VxD peut définir ses propres 'Messages de Contrôle' sur mesures qu'il peut utiliser pour communiquer avec d'autres VxDs qui les comprend.

Service APIs: Un VxD (un Device Virtuel), y compris le VMM (le Manager de Machine Virtuelle), exporte d'habitude un jeu des fonctions publiques qui peuvent être appelées par d'autres VxDs. Ces fonctions sont appelées des services VxD. Le mécanisme d'appel de ces services VxD diffère tout à fait de celui des applications en Ring-3. Chaque VxD qui exporte des services VxD DOITpossèder un numéro ID unique. Vous pouvez obtenir un tel n°ID de Microsoft. Le n°ID est un nombre sur 16 bits qui identifie uniquement un VxD. Par exemple,

Vous pouvez voir que le VMM (Manager de Machine Virtuelle) possède le n°ID 1, le VPICD a l'ID n°3 et ainsi de suite. Le VMM emploie cet ID unique pour trouver le VxD qui exporte les 'services VxD' demandés. Vous devez aussi choisir le service que vous voulez appeler par son index dans la table de branche de service. Quand un VxD exporte des services VxD, il stocke les adresses de ces services dans une table. Le VMM emploiera l'index fourni pour placer l'adresse du service souhaité dans la table de service. Par exemple, si vous voulez appeler GetVersion qui est le premier service, vous devez spécifier 0 (qui est l'index zéro-basé). Le mécanisme réel d'appel des 'services VxD' implique l'interruption 20 (int 20h). Dans votre code paraîtra l'instruction int 20h suivi d'une valeur de type dword qui sera composée du n°ID du dispositif (du clavier par exemple) et de l'index du service. Par exemple, si vous voulez appeler le service numéro 1 étant exporté par un VxD qui a le n°ID de dispositif de 000Dh, le code sera le suivant : Le mot de poids fort du dword qui suit l'instruction int 20h contient le n°ID du Device. Le mot de poids faible est l'index zéro-basé dans la table de service.
Quand int 20h est exécuté, le VMM prend le contrôle et examine le dword qui suit immédiatement cet instruction. Il en extrait alors le n°ID du dispositif et s'en sert pour localiser le VxD et emploie ensuite l'index de service pour y placer l'adresse du service désirée appartenant au VxD.
Vous pouvez remarquer que cette opération prend un certain temps. Le VMM (Manager de Machine Virtuelle) doit gaspiller du temps en localisant le VxD et l'adresse du service désiré. Ainsi le VMM triche un peu. Après que la première opération int 20h se soit passé, le VMM rompt la liaison. En rompant la liaison, ça signifie que le VMM remplace l'int 20h ainsi que le dword qui le suivit par un appel direct au service. Donc ce petit bout de code int 20h sera transformé en : Ce tour de passe passe marche parce que int 20h+dword prend 6 octets, qui est exactement de la mêmes taille que l'instruction call dword ptr. Donc les appels suivants sont rapides et efficaces. Cette méthode a son pour et son contre. Son bon côté, c'est de réduire le travail de chargement du VMM et du VxD parce qu'ils ne doivent pas fixer TOUS les appels de service de VxDs quand on les charge. Les appels qui ne sont jamais exécutés resteront non modifiés. Le mauvais côté, c'est qu'il est impossible de décharger un VxD statique une fois qu'on à fait appel à ses services et q'on s'y soit lié. Depuis que le VMM fixe les appels avec les adresses réelles des services VxD, si le VxD qui fournit ces services est déchargé de la mémoire, alors d'autres VxDs qui dépendent de ces services 'crasheront' probablement le système en faisant appel à des adresses mémoire invalides. Il n'y a aucun mécanisme pour assurer les liaisons. Le preuve c'est que les VxDs dynamiques ne sont pas appropriés comme les VxDs service providers.

Callbacks: Les fonctions callbacks ou callback sont des fonctions du VxD qui existent pour être appelés par d'autre VxDs. Ne faîtes pas la confusion entre les 'callbacks' et les 'VxD services'. Les callbacks ne sont pas publiques comme les services. Ce sont des fonctions privées que les adresses d'un VxD donnent à d'autres VxDs specifiques dans certaines situations. Par exemple, quand un VxD entretient une interruption matérielle, puisque le VMM n'est pas reparticipant (il ne traite qu'avec 1 seul), le VxD ne peut pas employer de 'VxD services' lesquels peuvent provoquer des fautes de page (en essayant de recommuniquer avec le VMM). Le VxD peut donner l'adresse de sa propre fonction (le callback) au VMM pour que celui-ci puisse appeler la fonction quand le VMM est capable de tolérer des fautes de page. Le VxD peut alors reprendre son travail quand sa fonction callback est appelée. Le concepte de callback n'est pas spécifique aux VxDs. Beaucoup d'APIs de Windows les emploient aussi. Le meilleur exemple est peut-être la 'procédure de fenêtre'. Vous spécifiez l'adresse d'une procédure de fenêtre dans la structure WNDCLASS ou WNDCLASSEX et la passez à Windows grâce à l'Appel de RegisterClassEx ou RegisterClass. Windows appellera votre procédure de fenêtre quand il y aura des messages destinés à cette fenêtre. Un autre exemple est la procédure de Hook. Votre application donne l'adresse de la procédure de Hook à Windows pour que celui-ci puisse l'appeler quand des événements intéressant pour votre application se produisent.

Ces trois méthodes servent à la communication entre VxDs. Il y a aussi les interfaces pour V86, le mode protégé et les applications Win32. Je couvrirai l'interface VxD pour les applications Win32 dans les Tutorials suivants.


[Iczelion's Win32 Assembly Homepage]


Traduit par Morgatte