Annulation des demandes d’E/S
L’opération d’E/S en cours d’un appareil (par exemple, une demande de lecture de plusieurs blocs à partir d’un disque) peut être annulée par une application, le système ou un pilote. Si l’opération d’E/S d’un appareil est annulée, le gestionnaire d’E/S tente d’annuler toutes les demandes d’E/S non traitées associées à l’opération d’E/S. Les pilotes de l’appareil peuvent s’inscrire pour être avertis lorsque le gestionnaire d’E/S tente d’annuler les demandes d’E/S, et les pilotes peuvent annuler les demandes qu’ils possèdent en les remplissant avec une status d’achèvement de STATUS_CANCELLED.
L’infrastructure gère une partie du travail d’annulation pour les pilotes basés sur l’infrastructure. Si l’opération d’E/S d’un appareil est annulée, l’infrastructure effectue les demandes d’E/S suivantes (avec une status d’achèvement de STATUS_CANCELLED) associées à l’opération annulée :
Demandes d’E/S non remises que l’infrastructure a placées dans la file d’attente d’E/S par défaut du pilote.
Demandes d’E/S non remises que l’infrastructure a transférées vers une autre file d’attente, car le pilote appelé WdfDeviceConfigureRequestDispatching.
Étant donné que l’infrastructure annule ces requêtes, elle ne les remet pas au pilote.
Une fois que l’infrastructure a remis une demande d’E/S au pilote, le pilote est propriétaire de la demande et l’infrastructure ne peut pas l’annuler. À ce stade, seul le pilote peut annuler la demande d’E/S, mais l’infrastructure doit informer le pilote qu’une demande doit être annulée. Les pilotes reçoivent cette notification en fournissant une fonction de rappel EvtRequestCancel .
Parfois, un pilote reçoit une demande d’E/S à partir d’une file d’attente d’E/S, mais, au lieu de traiter la demande, le pilote met la demande en file d’attente d’E/S identique ou dans une autre file d’attente d’E/S pour un traitement ultérieur. Voici quelques exemples de cette situation :
L’infrastructure fournit une demande d’E/S à l’un des gestionnaires de requêtes du pilote, et le pilote appelle ensuite WdfRequestForwardToIoQueue (ou WdfRequestForwardToParentDeviceIoQueue) pour placer la demande dans une autre file d’attente ou WdfRequestRequeue pour replacer la requête dans la même file d’attente.
L’infrastructure fournit une demande d’E/S à la fonction de rappel EvtIoInCallerContext du pilote, le pilote appelle WdfDeviceEnqueueRequest pour renvoyer la demande au framework, et l’infrastructure place ensuite la demande dans l’une des files d’attente d’E/S du pilote.
Dans ce cas, l’infrastructure peut annuler la demande d’E/S, car elle se trouve dans une file d’attente d’E/S. Toutefois, si le pilote a inscrit une fonction de rappel EvtIoCanceledOnQueue pour la file d’attente d’E/S dans laquelle réside la demande, l’infrastructure appelle la fonction de rappel, au lieu d’annuler la demande, lorsque l’opération d’E/S associée est annulée. Si l’infrastructure appelle la fonction de rappel EvtIoCanceledOnQueue du pilote, le pilote doit terminer la demande.
En résumé, lorsqu’une opération d’E/S est annulée, l’infrastructure annule toujours toutes les demandes d’E/S associées qui n’ont jamais été remises au pilote. Si le pilote reçoit une demande et la met en file d’attente, l’infrastructure annule la demande (si la requête se trouve dans la file d’attente), sauf si le pilote fournit une fonction de rappel EvtIoCanceledOnQueue pour la file d’attente d’E/S.
Appel de WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx
Un pilote peut appeler WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx pour inscrire une fonction de rappel EvtRequestCancel . Si le pilote a appelé WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx, et si l’opération d’E/S associée à la demande est annulée, l’infrastructure appelle la fonction de rappel EvtRequestCancel du pilote afin que le pilote puisse annuler la demande d’E/S.
Un pilote doit appeler WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx s’il possède une demande pendant une période relativement longue. Par exemple, un pilote peut devoir attendre qu’un appareil réponde, ou il peut attendre que les pilotes inférieurs répondent à un ensemble de demandes créées par le pilote lorsqu’il a reçu une seule requête.
Si un pilote n’appelle pas WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx, ou si un pilote appelle WdfRequestUnmarkCancelable après avoir appelé WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx, le pilote n’est pas au courant de l’annulation et gère donc la demande comme il le ferait normalement.
Appel de WdfRequestIsCanceled
Si un pilote n’a pas appelé WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx pour inscrire une fonction de rappel EvtRequestCancel , il peut appeler WdfRequestIsCanceled pour déterminer si le gestionnaire d’E/S a tenté d’annuler une demande d’E/S. Si WdfRequestIsCanceled retourne TRUE et que le pilote est propriétaire de la demande, le pilote doit annuler la demande. Si le pilote n’est pas propriétaire de la demande, il ne doit pas appeler WdfRequestIsCanceled.
Un pilote qui n’a pas appelé WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx peut appeler WdfRequestIsCanceled dans les circonstances suivantes :
Un pilote qui attend des interruptions d’appareil peut appeler WdfRequestIsCanceled à partir de sa fonction de rappel EvtInterruptDpc .
Un pilote qui interroge son appareil peut appeler WdfRequestIsCanceled à partir de son thread d’interrogation.
Un pilote qui interrompt une transaction DMA en plusieurs transferts plus petits peut appeler WdfRequestIsCanceled une fois chaque transfert terminé.
Un pilote qui reçoit une demande de lecture ou d’écriture volumineuse qu’il décompose en plusieurs requêtes plus petites peut appeler WdfRequestIsCanceled une fois que la cible d’E/S du pilote a terminé chacune des demandes plus petites, si le pilote n’a pas appelé WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx pour la demande reçue.
Annulation de la demande
L’annulation d’une demande d’E/S peut impliquer l’un des éléments suivants :
Arrêt d’une opération d’E/S en cours.
Ne pas transférer la demande à une cible d’E/S.
Appel de WdfRequestCancelSentRequest pour tenter d’annuler une demande que le pilote avait précédemment soumise à une cible d’E/S.
Si un pilote annule une demande d’E/S pour un objet de requête que le pilote a reçu de l’infrastructure, il doit toujours terminer la demande en appelant WdfRequestComplete, WdfRequestCompleteWithInformation ou WdfRequestCompleteWithPriorityBoost, avec un paramètre Status de STATUS_CANCELLED. (Si le pilote a appelé WdfRequestCreate pour créer un objet de requête, le pilote appelle WdfObjectDelete au lieu de terminer la requête.)
Synchronisation de l’annulation
Pour plus d’informations sur la synchronisation du code qui annule les demandes d’E/S, consultez :