Partager via


Points à prendre en compte lors de l’annulation d’IRPs

Cette section décrit les instructions relatives à l’implémentation d’une routine d’annulation et à la gestion des IRP annulables. Pour plus d’informations sur la gestion des IRPs annulables, consultez le flux de contrôle pour Cancel-Safe IRP Queuing.

Instructions générales pour toutes les routines d’annulation

Le gestionnaire d’E/S contient le verrou de rotation d’annulation chaque fois qu’il appelle la routine Cancel d’un pilote. Par conséquent, chaque routine d’annulation doit :

  • Appelez IoReleaseCancelSpinLock avant que la fonction ne rende le contrôle.

  • N’appelez pas IoAcquireCancelSpinLock à moins d'avoir appelé IoReleaseCancelSpinLock en premier.

  • Effectuez un appel réciproque à IoReleaseCancelSpinLock pour chaque appel effectué à IoAcquireCancelSpinLock.

Chaque fois que la routine Cancel appelle IoReleaseCancelSpinLock, elle doit passer l’IRQL retourné par l’appel le plus récent à IoAcquireCancelSpinLock. Lors de la libération du verrou de rotation acquis par le gestionnaire d’E/S (et conservé lorsque la routine Cancel a été appelée), la routine Cancel doit passer Irp-CancelIrql>.

Un pilote ne doit pas appeler des routines extérieures (par exemple IoCompleteRequest) lors de la conservation d’un verrou de rotation, car un interblocage peut se produire.

Utilisation de la file d’attente définie par le Gestionnaire d’E/S

À moins qu’un pilote ne gère ses propres files d’attente internes d’IRPs, sa routine Cancel est appelée avec un IRP reçu qui peut être l'un des suivants :

  • CurrentIrp dans l’objet d’appareil cible d’entrée

  • Entrée dans la file d’attente de l’appareil associée à l’objet d’appareil cible

Sauf si un pilote gère ses propres files d’attente internes d’IRPs, sa routine Cancel doit appeler KeRemoveEntryDeviceQueue avec l’IRP d’entrée pour tester s’il s’agit d’une entrée dans la file d’attente de l’appareil associée à l’objet d’appareil cible. La routine Cancel du pilote ne peut pas appeler KeRemoveDeviceQueue ou KeRemoveByKeyDeviceQueue , car elle ne peut pas supposer que l’IRP donné se trouve à une position particulière dans la file d’attente de l’appareil.

État actuel de l’IRP d’entrée

Si une routine Cancel est appelée avec un IRP pour lequel le pilote a déjà démarré le traitement des E/S et que la demande sera bientôt terminée, la routine Cancel doit libérer le verrou de boucle d'attente d’annulation du système et restituer le contrôle.

Si l’état actuel de l’IRP d’entrée est en attente, une routine d’annulation doit effectuer les opérations suivantes :

  1. Définissez le bloc d’état d’E/S d’entrée avec STATUS_CANCELLED pour l’état et zéro pour les informations.

  2. Relâchez tous les verrous de rotation qu'il détient, y compris le verrou de rotation d'annulation du système.

  3. Appelez IoCompleteRequest avec l’IRP donné.

Conservation d’IRPs dans un état annulable

Toute routine de pilote qui contient un IRP dans un état annulable doit appeler IoMarkIrpPending et doit appeler IoSetCancelRoutine pour définir son point d’entrée pour la routine Cancel dans l’IRP. Ce n'est qu'alors que cette routine de pilote peut appeler des routines de support supplémentaires telles que IoStartPacket, IoAllocateController, ou une routine ExInterlockedInsert..List.

Toute routine de pilote qui traite par la suite les IRP pouvant être annulées doit vérifier si un IRP a déjà été annulé avant de commencer les opérations pour répondre à la demande. La routine doit appeler IoSetCancelRoutine pour réinitialiser son point d’entrée pour la routine Cancel sur NULL dans l’IRP. Ce n'est qu'à ce moment-là que cette routine peut commencer à effectuer son traitement d’entrée/sortie pour l’IRP de saisie.

Une routine peut avoir à réinitialiser le point d’entrée d’une routine Annuler dans un IRP si elle, également, transmet les IRPs pour un traitement ultérieur par d’autres routines de pilotes, et ces IRPs peuvent être maintenus dans un état annulable.

Tout pilote de niveau supérieur qui contient un IRP dans un état annulable doit réinitialiser son point d’entrée Cancel sur NULL avant de passer l’IRP au pilote suivant avec IoCallDriver.

Annulation d’un IRP

Tout pilote de niveau supérieur peut appeler IoCancelIrp avec un IRP qu’il a alloué et transmis pour un traitement ultérieur par des pilotes de niveau inférieur. Toutefois, un tel driver ne peut pas supposer que l’IRP donné sera achevé avec le statut STATUS_CANCELLED par des drivers de niveau inférieur.

Synchronisation

Un pilote peut (ou doit, selon sa conception) conserver des informations d’état supplémentaires dans son extension de périphérique pour suivre la possibilité d'annulation des IRPs. Si cet état est partagé par les routines de pilote s’exécutant à IRQL <= DISPATCH_LEVEL, les données partagées doivent être protégées par un verrou de rotation alloué et initialisé par le pilote.

Le pilote doit gérer ses acquisitions et ses libérations du spin lock d’annulation du système et ses propres spin locks avec soin. Il doit détenir le verrou de rotation d’annulation du système pendant les intervalles les plus courts possibles. Avant d’accéder à un IRP annulable, un tel pilote doit toujours vérifier la valeur de retour d’IoSetCancelRoutine pour déterminer si la routine Cancel est déjà en cours d’exécution (ou est sur le point d’être exécutée) ; si c’est le cas, il doit laisser la routine Annuler terminer l’IRP.

Si un pilote de périphérique conserve des informations d’état sur les irPs annulables que les différentes routines de pilotes partagent avec son ISR, ces autres routines doivent synchroniser l’accès à l’état partagé avec l’ISR. Seule une routine SynchCritSection fournie par le pilote peut accéder aux informations d’état partagées avec l’ISR d’une manière multiprocesseur sécurisée.

Pour plus d’informations, consultez Techniques de synchronisation.