Partager via


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

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

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

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

  • Appelez IoReleaseCancelSpinLock avant qu’il ne retourne le contrôle.

  • N’appelez pas IoAcquireCancelSpinLock , sauf s’il appelle IoReleaseCancelSpinLock en premier.

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

Chaque fois que la routine Cancel appelle IoReleaseCancelSpinLock, elle doit transmettre 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é lors de l’appel de la routine Cancel), la routine Cancel doit passer Irp-CancelIrql>.

Un pilote ne doit pas appeler des routines externes (telles qu’IoCompleteRequest) tout en tenant un verrou de rotation, car un blocage 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 entrant qui peut être l’un des éléments suivants :

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

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

À moins qu’un pilote ne 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 d’appareils 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 des appareils.

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

Si une routine d’annulation 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 contrôle d’annulation et de retour du système.

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

  1. Définissez le bloc d’E/S de l’entrée IRP status avec STATUS_CANCELLED pour Status et zéro pour Information.

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

  3. Appelez IoCompleteRequest avec l’IRP donné.

Conservation des 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 un ExInterlockedInsert.. Lister la routine.

Toute routine de pilote qui traite par la suite les IRP annulables doit case activée 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’alors que cette routine peut commencer son traitement d’E/S pour l’IRP d’entrée.

Une routine peut devoir réinitialiser le point d’entrée d’une routine Cancel dans un IRP si elle, elle aussi, transmet des IRPs pour un traitement ultérieur par d’autres routines de pilotes et que ces IRPs peuvent être conservés 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 inférieur 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 pilote ne peut pas supposer que l’IRP donné sera complété avec STATUS_CANCELLED par les pilotes inférieurs.

Synchronization

Un pilote peut (ou doit, selon sa conception) conserver des informations d’état supplémentaires dans son extension d’appareil pour suivre les status annulables des IRPs. Si cet état est partagé par des 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é au pilote et initialisé.

Le pilote doit gérer soigneusement ses acquisitions et les mises en production du verrou d’annulation de rotation du système et de ses propres verrous de rotation. Il doit contenir 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 case activée 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 de s’exécuter). Si c’est le cas, il doit laisser la routine Cancel terminer l’IRP.

Si un pilote de périphérique conserve des informations d’état sur les IRP annulables que diverses 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 un pilote peut accéder aux informations d’état partagées avec l’ISR d’une manière sécurisée multiprocesseur.

Pour plus d’informations, consultez Techniques de synchronisation.