Exemple de demande d’E/S - Détails
La figure illustrant l’ouverture d’un objet fichier montre un IRP avec deux emplacements de pile d’E/S, mais un IRP peut avoir n’importe quel nombre d’emplacements de pile d’E/S, en fonction du nombre de pilotes en couches qui gèrent une requête donnée.
La figure suivante illustre plus en détail comment les pilotes de la figure Ouverture d’un objet fichier utilisent des routines de prise en charge des E/S (routines IoXxx ) pour traiter l’IRP pour une demande de lecture ou d’écriture.
Le gestionnaire d’E/S appelle le pilote de système de fichiers (FSD) avec l’IRP qu’il a alloué pour la demande de lecture/écriture du sous-système. Le FSD accède à son emplacement de pile d’E/S dans l’IRP pour déterminer l’opération qu’il doit effectuer.
Le FSD peut diviser la demande d’origine en demandes plus petites (éventuellement pour plusieurs pilotes de périphérique) en appelant une routine de prise en charge des E/S (IoAllocateIrp) une ou plusieurs fois pour allouer des IRP supplémentaires. Les IRP supplémentaires sont retournés au FSD avec un ou plusieurs emplacements de pile d’E/S à remplissage zéro pour les pilotes de niveau inférieur. À sa discrétion, le FSD peut réutiliser l’IRP d’origine, plutôt que d’allouer des IRPs supplémentaires comme indiqué dans la figure précédente, en configurant l’emplacement de pile d’E/S du pilote inférieur suivant dans l’IRP d’origine et en le transmettant aux pilotes inférieurs.
Pour chaque IRP alloué au pilote, le FSD de la figure précédente appelle une routine de prise en charge des E/S pour inscrire une routine d’achèvement fournie par le FSD ; dans la routine d’achèvement, le FSD peut déterminer si les pilotes inférieurs ont satisfait à la demande et peut libérer chaque IRP alloué au pilote lorsque les pilotes inférieurs l’ont terminé. Le gestionnaire d’E/S appelle la routine de saisie semi-automatique fournie par le FSD, que chaque IRP alloué au pilote ait été terminé avec succès, terminé avec une status d’erreur ou annulé. Un pilote de niveau supérieur est chargé de libérer tous les IRP qu’il alloue et qu’il configure pour son propre compte pour les pilotes de niveau inférieur. Le gestionnaire d’E/S libère les IRP qu’il alloue une fois que tous les pilotes les ont terminés.
Ensuite, le FSD appelle une routine de prise en charge des E/S (IoGetNextIrpStackLocation) pour accéder à l’emplacement de la pile d’E/S du pilote de niveau inférieur suivant afin de configurer la demande pour le pilote inférieur suivant. (Dans la figure précédente, le pilote inférieur suivant se trouve être le pilote de niveau le plus bas.) Le FSD appelle ensuite une routine de prise en charge des E/S (IoCallDriver) pour passer cette IRP au pilote inférieur suivant.
Lorsqu’il est appelé avec l’IRP, le pilote de niveau le plus bas vérifie son emplacement de pile d’E/S pour déterminer l’opération (indiquée par le code de la fonction IRP_MJ_XXX ) qu’il doit effectuer sur l’appareil cible. L’appareil cible est représenté par l’objet d’appareil dans son emplacement de pile d’E/S désigné et est passé avec l’IRP au pilote. Le pilote de niveau le plus bas peut supposer que le gestionnaire d’E/S a acheminé l’IRP vers un point d’entrée défini par le pilote pour l’opération IRP_MJ_XXX (ici IRP_MJ_READ ou IRP_MJ_WRITE) et que le pilote de niveau supérieur a vérifié la validité des autres paramètres de la demande.
S’il n’y avait pas de pilote de niveau supérieur, le pilote de niveau le plus bas case activée si les paramètres d’entrée d’une opération IRP_MJ_XXX sont valides. Si tel est le cas, le pilote appelle généralement des routines de prise en charge des E/S pour indiquer au gestionnaire d’E/S qu’une opération d’appareil est en attente sur l’IRP et pour mettre en file d’attente l’IRP ou la transmettre à une autre routine fournie par le pilote qui accède à l’appareil cible (ici, un périphérique physique ou logique : le disque ou une partition sur le disque).
Le gestionnaire d’E/S détermine si le pilote est déjà occupé à traiter un autre IRP pour l’appareil cible, met en file d’attente l’IRP le cas échéant et retourne. Sinon, le gestionnaire d’E/S achemine l’IRP vers une routine fournie par le pilote qui démarre l’opération d’E/S sur son appareil. (À ce stade, les pilotes de la figure précédente et le contrôle du gestionnaire d’E/S retournent.)
Lorsque l’appareil s’interrompt, la routine de service d’interruption (ISR) du pilote ne fait que le travail nécessaire pour empêcher l’appareil d’interrompre et pour enregistrer le contexte nécessaire à propos de l’opération. L’ISR appelle ensuite une routine de prise en charge des E/S (IoRequestDpc) avec l’IRP pour mettre en file d’attente une routine DPC (Appel de procédure différée) fournie par le pilote pour terminer l’opération demandée à une priorité matérielle inférieure à celle de l’ISR.
Lorsque le DPC du pilote obtient le contrôle, il utilise le contexte (passé dans l’appel de l’ISR à IoRequestDpc) pour terminer l’opération d’E/S. Le DPC appelle une routine de prise en charge pour mettre en file d’attente le IRP suivant (le cas échéant) et pour passer cette IRP à la routine fournie par le pilote qui démarre les opérations d’E/S sur l’appareil (voir Étape 5). Le DPC définit ensuite status sur l’opération qui vient de s’achever dans le bloc de status d’E/S de l’IRP et le retourne au gestionnaire d’E/S avec IoCompleteRequest.
Le gestionnaire d’E/S supprime l’emplacement de la pile d’E/S du pilote de niveau le plus bas dans l’IRP et appelle la routine d’achèvement inscrite du système de fichiers (voir Étape 3) avec l’IRP alloué au FSD. Cette routine d’achèvement vérifie le bloc d’E/S status pour déterminer s’il faut réessayer la demande ou mettre à jour l’état interne conservé concernant la demande d’origine et libérer son IRP alloué au pilote. Le système de fichiers peut collecter status informations pour tous les IRP alloués aux pilotes qu’il envoie aux pilotes de niveau inférieur afin de pouvoir définir les status d’E/S et terminer l’IRP d’origine. Lorsque le système de fichiers a terminé l’IRP d’origine, le gestionnaire d’E/S retourne et la valeur NTSTATUS au demandeur d’origine (la fonction native du sous-système) de l’opération d’E/S.
Comme le pilote de système de fichiers indiqué dans la figure Traitement des IRP dans les pilotes en couches , tout nouveau pilote ajouté à une chaîne de pilotes existants peut effectuer les opérations suivantes :
Définissez sa propre routine d’achèvement dans un IRP. La routine IoCompletion vérifie le bloc d’E/S status pour déterminer si les pilotes inférieurs ont terminé l’IRP avec succès, annulé l’IRP et/ou l’ont terminé avec une erreur. La routine d’achèvement peut également mettre à jour n’importe quel état spécifique à l’IRP que le pilote a enregistré, libérer toutes les ressources spécifiques à l’opération que le pilote a allouées, et ainsi de suite, avant de terminer l’IRP. En outre, la routine d’achèvement peut différer l’achèvement de l’IRP (en informant le gestionnaire d’E/S qu’un traitement supplémentaire est nécessaire sur l’IRP) et peut envoyer une autre demande au pilote de niveau inférieur suivant avant d’autoriser l’IRP à se terminer.
Configurez l’emplacement de la pile d’E/S du pilote de niveau inférieur suivant dans les IRP qu’il alloue et envoyez des requêtes au pilote de niveau inférieur suivant.
Transmettez toutes les requêtes entrantes aux pilotes inférieurs en configurant l’emplacement de la pile d’E/S du pilote inférieur suivant dans chaque IRP et en appelant IoCallDriver. (Notez que pour les IRP avec le code de fonction principal IRP_MJ_POWER, les pilotes doivent utiliser PoCallDriver.)
Chaque objet d’appareil créé par un pilote représente un appareil physique, logique ou virtuel pour lequel un pilote particulier effectue des demandes d’E/S. Pour plus d’informations sur la création et la configuration d’un objet d’appareil, consultez Device Objects and Device Stacks.
Comme le montre également la figure Traitement des IRP dans les pilotes en couches , la plupart des pilotes traitent chaque IRP par étapes via un ensemble de routines standard définies par le système fournis par le pilote, mais les pilotes à différents niveaux d’une chaîne ont nécessairement des routines standard différentes. Par exemple, seuls les pilotes de niveau le plus bas gèrent les interruptions d’un appareil physique. Par conséquent, seul un pilote de niveau le plus bas aurait un ISR et un DPC qui termine les opérations d’E/S pilotées par interruption. D’autre part, comme un tel pilote sait que les E/S sont terminées lorsqu’il reçoit une interruption de son appareil, il n’a pas besoin d’une routine d’achèvement. Seul un pilote de niveau supérieur aurait une ou plusieurs routines d’achèvement comme le FSD dans cette figure.