Partager via


Traitement des IRP dans un pilote Intermediate-Level

Les pilotes de niveau supérieur ont un ensemble de routines standard différent des pilotes de périphériques de niveau inférieur, avec un sous-ensemble de routines standard qui se chevauchent pour les deux types de pilotes.

L’ensemble des routines pour les pilotes intermédiaires et les pilotes de niveau supérieur varie également en fonction des critères suivants :

  • La nature de l’appareil physique sous-jacent

  • Indique si un pilote de périphérique sous-jacent configure des objets de périphérique pour les E/S directes ou mises en mémoire tampon

  • La conception du pilote de niveau supérieur individuel

La figure suivante illustre le chemin d’accès qu’un IRP peut emprunter à travers les routines standard d’un pilote intermédiaire miroir superposé quelque part sur le pilote de périphérique de niveau le plus bas décrit dans la section précédente.

Le pilote illustré dans la figure suivante présente les caractéristiques suivantes :

  • Le pilote est superposé sur plusieurs périphériques physiques et éventuellement sur plusieurs pilotes de périphérique.

  • Le pilote alloue parfois des IRP supplémentaires pour les pilotes de niveau inférieur, en fonction de l’opération demandée dans l’IRP d’entrée.

  • Le pilote a au moins un pilote de système de fichiers en couches au-dessus, et ce pilote de système de fichiers peut être superposé à d’autres pilotes intermédiaires à un niveau supérieur à celui-ci.

diagramme illustrant un chemin d’accès irp via des routines de pilotes intermédiaires.

Comme le montre la figure, le gestionnaire d’E/S crée un IRP et l’envoie à la routine de répartition du pilote pour le code de fonction principale donné. En supposant que le code de la fonction est IRP_MJ_WRITE, la routine de répartition est DDDispatchWrite. L’emplacement de la pile d’E/S du pilote intermédiaire est affiché au milieu, avec un nombre indéfini d’emplacements de pile d’E/S pour les pilotes de niveau supérieur et inférieur affichés ombrés.

Allocation de runtimes d’intégration

L’objectif du pilote miroir est d’envoyer des demandes d’écriture à plusieurs appareils physiques et d’envoyer des demandes de lecture alternativement aux pilotes de ces appareils. Pour les demandes d’écriture, le pilote crée des runtimes d’intégration en double pour chaque appareil sur lequel les données doivent être écrites, en supposant que les paramètres dans l’IRP d’entrée sont valides.

La figure précédente montre un appel à IoAllocateIrp , mais les pilotes de niveau supérieur peuvent appeler d’autres routines de support pour allouer des IRP aux pilotes de niveau inférieur. Consultez Création de runtimes d’intégration pour les pilotes Lower-Level.

Lorsque la routine de répartition appelle IoAllocateIrp, elle spécifie le nombre d’emplacements de pile d’E/S nécessaires pour l’IRP. Le pilote doit spécifier un emplacement de pile pour chaque pilote inférieur de la chaîne, en obtenant la valeur appropriée à partir des objets de périphérique de chaque pilote juste en dessous du pilote miroir. Si vous le souhaitez, le pilote peut en ajouter un à cette valeur lorsqu’il appelle IoAllocateIrp pour obtenir son propre emplacement de pile pour chaque IRP qu’il alloue, comme le fait le pilote dans la figure précédente.

La routine de répartition de ce pilote intermédiaire appelle IoGetCurrentIrpStackLocation (non affiché) avec l’IRP d’origine pour case activée paramètres.

Il appelle IoSetNextIrpStackLocation , car il a alloué son propre emplacement de pile dans chaque IRP nouvellement créé et IoGetCurrentIrpStackLocation pour créer un contexte pour lui-même qu’il utilisera plus tard dans la routine IoCompletion .

Ensuite, il appelle IoGetNextIrpStackLocation avec chaque IRP nouvellement créé afin de pouvoir configurer les emplacements de pile d’E/S de niveau inférieur suivants dans les IRP qu’il a alloués. La routine de distribution du pilote miroir copie les codes et paramètres de la fonction IRP (pointeur vers la mémoire tampon de transfert, longueur en octets à transférer pour IRP_MJ_WRITE) dans les emplacements de pile d’E/S pour les pilotes inférieurs suivants. Ces pilotes, à leur tour, configurent les emplacements de pile d’E/S pour les pilotes juste en dessous d’eux, le cas échéant.

Appel d’IoSetCompletionRoutine et IoCallDriver

La routine de répartition dans la figure précédente appelle IoSetCompletionRoutine pour chaque IRP qu’elle a allouée. Étant donné que le pilote de la figure précédente doit supprimer les IRP qu’il a alloués, ce pilote définit sa routine IoCompletion pour qu’elle soit appelée lorsque les pilotes inférieurs terminent ses IRP, si l’opération d’E/S s’est terminée correctement, a échoué ou a été annulée.

Étant donné que le pilote de la figure précédente est en miroir en parallèle, il transmet les deux irps qu’il a alloués aux pilotes de niveau inférieur suivant en appelant IoCallDriver deux fois, une fois pour chaque objet d’appareil cible représentant une partition mise en miroir.

Traitement des irps dans la routine IoCompletion du pilote

Lorsque l’un des ensembles de pilotes de niveau inférieur termine l’opération demandée, le gestionnaire d’E/S appelle la routine IoCompletion du pilote miroir intermédiaire. Le pilote miroir conserve un nombre dans son propre emplacement de pile d’E/S pour l’IRP d’origine, afin de suivre le moment où les pilotes inférieurs ont terminé toutes les irps en double.

En supposant que le bloc d’E/S status indique qu’un ensemble de pilotes inférieurs a terminé le IRP en double illustré dans la figure précédente, la routine IoCompletion du pilote miroir décrémente son nombre, mais ne peut pas terminer l’IRP d’origine tant qu’elle n’a pas décrémenté le nombre à zéro. Si le nombre décrémenté n’est pas encore égal à zéro, la routine IoCompletion appelle IoFreeIrp avec le premier IRP (DupIRP1 dans la figure précédente) que le pilote a alloué et retourne STATUS_MORE_PROCESSING_REQUIRED.

Lorsque la routine IoCompletion du pilote miroir est appelée à nouveau avec le DupIRP2 illustré dans la figure précédente, la routine IoCompletion décrémente le nombre dans l’IRP d’origine et détermine que les deux ensembles de pilotes de niveau inférieur ont effectué les opérations demandées.

En supposant que le bloc de status d’E/S dans DupIRP2 est également défini avec STATUS_SUCCESS, la routine IoCompletion copie le bloc d’E/S status de DupIRP2 dans l’IRP d’origine et libère DupIRP2. Il appelle IoCompleteRequest avec l’IRP d’origine et retourne STATUS_MORE_PROCESSING_REQUIRED. Le renvoi de cette status empêche le gestionnaire d’E/S de tenter de poursuivre le traitement d’achèvement sur DupIRP2 ; étant donné que l’IRP n’est pas associé à un thread, son traitement d’achèvement doit se terminer par le pilote qui l’a créé.

Si l’un des ensembles de pilotes de niveau inférieur ne termine pas correctement les miroir les IRP du pilote, la routine IoCompletion du pilote miroir doit consigner une erreur et tenter la récupération de données en miroir appropriée. Pour plus d’informations, consultez Erreurs de journalisation.