Partager via


Forcer les demandes d’E/S en attente

L’option Forcer les demandes d’E/S en attente retourne de manière aléatoire STATUS_PENDING en réponse aux appels d’un pilote à IoCallDriver. Cette option teste la logique du pilote pour répondre aux valeurs de retour STATUS_PENDING à partir d’IoCallDriver.

Cette option est prise en charge uniquement sur Windows Vista et les versions ultérieures du système d’exploitation Windows.

Attention N’utilisez pas cette option sur un pilote, sauf si vous avez une connaissance détaillée du fonctionnement du pilote et que vous avez vérifié que le pilote est conçu pour gérer STATUS_PENDING retour de valeurs de tous ses appels à IoCallDriver. L’exécution de cette option sur un pilote qui n’est pas conçu pour gérer STATUS_PENDING de tous les appels peut entraîner des incidents, des altérations de la mémoire et un comportement système inhabituel qui peut être difficile à déboguer ou corriger.

Pourquoi utiliser forcer les demandes d’E/S en attente ?

Les pilotes de niveau supérieur dans une pile de pilotes appellent IoCallDriver pour passer un IRP aux pilotes de niveau inférieur dans la pile de pilotes. La routine de répartition du pilote dans le pilote de niveau inférieur qui reçoit l’IRP peut soit terminer l’IRP immédiatement, soit retourner STATUS_PENDING et terminer l’IRP ultérieurement.

En règle générale, l’appelant doit être prêt à gérer l’un ou l’autre des résultats. Toutefois, étant donné que la plupart des routines de répartition gèrent immédiatement l’IRP, la logique STATUS_PENDING dans l’appelant n’est pas souvent exercée et des erreurs logiques graves peuvent ne pas être détectées. L’option Forcer les demandes d’E/S en attente intercepte les appels à IoCallDriver et retourne STATUS_PENDING pour tester la logique rarement utilisée du pilote appelant.

Quand utilisez-vous Forcer les demandes d’E/S en attente ?

Avant d’exécuter ce test, passez en revue la conception du pilote et le code source et vérifiez que le pilote est destiné à gérer STATUS_PENDING de tous ses appels IoCallDriver .

De nombreux pilotes ne sont pas conçus pour gérer STATUS_PENDING sur tous les appels à IoCallDriver. Ils peuvent envoyer l’IRP à un pilote bien connu particulier qui est garanti pour terminer l’IRP immédiatement. L’envoi de STATUS_PENDING à un pilote qui ne les gère pas peut entraîner des blocages du pilote et du système et une altération de la mémoire.

Comment les conducteurs doivent-ils gérer STATUS_PENDING ?

Le pilote de niveau supérieur qui appelle IoCallDriver doit gérer une valeur de retour STATUS_PENDING comme suit :

  • Avant d’appeler IoCallDriver, le pilote doit appeler IoBuildSynchronousFsdRequest pour organiser le traitement synchrone de l’IRP.

  • Si IoCallDriver retourne STATUS_PENDING, le pilote doit attendre la fin de l’IRP en appelant KeWaitForSingleObject sur l’événement spécifié.

  • Le pilote doit prévoir que l’IRP peut être libéré avant que le gestionnaire d’E/S signale l’événement.

  • Après avoir appelé IoCallDriver, l’appelant ne peut pas référencer l’IRP.

Quelles erreurs force la demande d’E/S en attente détecte-t-elle ?

L’option Forcer la demande d’E/S en attente détecte les erreurs suivantes dans le pilote qui appelle IoCallDriver et reçoit une valeur de retour STATUS_PENDING :

  • Le pilote n’appelle pas IoBuildSynchronousFsdRequest pour organiser le traitement synchrone.

  • Le pilote n’appelle pas KeWaitForSingleObject.

  • Le pilote référence une valeur dans la structure IRP après avoir appelé IoCallDriver. Après avoir appelé IoCallDriver, le pilote de niveau supérieur ne peut pas accéder à l’IRP, sauf s’il a défini une routine d’achèvement, puis uniquement lorsque tous les pilotes de niveau inférieur ont terminé l’IRP. Si l’IRP est libéré, le pilote se bloque.

  • Le pilote appelle une fonction associée de manière incorrecte. Par exemple, le pilote appelle KeWaitForSingleObject et transmet un handle à l’événement (en tant que paramètre Object ), au lieu de passer un pointeur vers un objet événement.

  • Le pilote attend le mauvais événement. Par exemple, le pilote appelle IoSetCompletionRoutine, mais attend un événement interne signalé par sa propre routine d’achèvement, au lieu d’attendre l’événement IRP signalé par le gestionnaire d’E/S lorsque l’IRP est terminé.

Forcer les modifications des demandes d’E/S en attente introduites dans Windows 7

À compter de Windows 7, l’option Forcer les demandes d’E/S en attente est plus efficace pour forcer l’exercice des chemins de code STATUS_PENDING dans les pilotes vérifiés. Dans les versions antérieures de Windows, driver verifier forçait le retard d’une complétion IRP uniquement lorsque la première demande IoCompleteRequest pour cette IRP s’exécute. Cela signifie que l’efficacité de la vérification de Driver1 peut être réduite par le comportement de Driver2 à partir de la même pile de périphériques. Driver2 peut attendre de façon synchrone l’achèvement avant de revenir de sa routine de distribution à Driver1. Le retard forcé de l’achèvement de l’IRP se produit précisément avant que la demande d’E/S ne se déroule dans le pilote vérifié sur le chemin d’achèvement. Cela signifie que le chemin de code STATUS_PENDING du pilote vérifié est réellement exercé et que le pilote vérifié perçoit un retard dans l’exécution.

Activation de cette option

Pour activer Forcer les demandes d’E/S en attente, vous devez également activer la vérification des E/S. Vous pouvez activer l’option Forcer les demandes d’E/S en attente pour un ou plusieurs pilotes à l’aide du Gestionnaire du vérificateur de pilotes ou de la ligne de commande Verifier.exe. Pour plus d’informations, consultez Sélection des options du vérificateur de pilote.

L’option Forcer les demandes d’E/S en attente est prise en charge uniquement sur Windows Vista et les versions ultérieures de Windows.

  • Sur la ligne de commande

    Pour activer Forcer les demandes d’E/S en attente, utilisez une valeur d’indicateur de 0x210 ou ajoutez 0x210 à la valeur de l’indicateur. Cette valeur active la vérification des E/S (0x10) et force les demandes d’E/S en attente (0x200).

    Par exemple :

    verifier /flags 0x210 /driver MyDriver.sys
    

    L’option sera active après le prochain démarrage.

    Si vous essayez d’activer uniquement Forcer les demandes d’E/S en attente (vérificateur /indicateurs 0x200), le vérificateur de pilote active automatiquement force les demandes d’E/S en attente (0x200) et la vérification d’E/S.

    Vous pouvez également activer et désactiver Forcer les demandes d’E/S en attente sans redémarrer l’ordinateur en ajoutant le paramètre /volatile à la commande. Par exemple :

    verifier /volatile /flags 0x210 /adddriver MyDriver.sys
    

    Ce paramètre prend effet immédiatement, mais il est perdu lorsque vous arrêtez ou redémarrez l’ordinateur. Pour plus d’informations, consultez Utilisation de paramètres volatiles.

  • Utilisation du Gestionnaire du vérificateur de pilotes

    1. Démarrez le Gestionnaire du vérificateur de pilotes. Tapez Vérificateur dans une fenêtre d’invite de commandes.
    2. Sélectionnez Créer des paramètres personnalisés (pour les développeurs de code), puis cliquez sur Suivant.
    3. Sélectionnez Sélectionner des paramètres individuels dans une liste complète.
    4. Sélectionnez Vérification des E/S et Forcer les demandes d’E/S en attente.

    Si vous sélectionnez uniquement Forcer les demandes d’E/S en attente, le Gestionnaire du vérificateur de pilotes vous rappelle que la vérification des E/S est requise et propose de l’activer pour vous.

Affichage des résultats

Pour afficher les résultats du test Forcer les demandes d’E/S en attente, utilisez l’extension du débogueur !verifier avec la valeur d’indicateur 0x40.

Pour plus d’informations sur !verifier, consultez la rubrique !verifier dans la documentation Outils de débogage pour Windows .

Si la machine de test se bloque à la suite du test Forcer les demandes d’E/S en attente, vous pouvez utiliser la commande !verifier 40 pour en trouver la cause. Dans une trace de pile actuelle, recherchez l’adresse de l’IRP qui a été récemment utilisée par votre pilote. Par exemple, si vous utilisez la commande kP , qui affiche le cadre de pile d’un thread, vous pouvez trouver l’adresse IRP parmi les paramètres de fonction de la trace de pile actuelle. Ensuite, exécutez !verifier 40 et recherchez l’adresse de l’IRP. Les traces de pile en attente de force les plus récentes s’affichent en haut de l’affichage.

Par exemple, la trace de pile suivante de Pci.sys affiche sa réponse à Forcer les demandes d’E/S en attente. Le test ne révèle aucune erreur dans la logique Pci.sys.

kd> !verifier 40
# Size of the log is 0x40
========================================================
IRP: 8f84ef00 - forced pending from stack trace:

     817b21e4 nt!IovpLocalCompletionRoutine+0xb2
     81422478 nt!IopfCompleteRequest+0x15c
     817b2838 nt!IovCompleteRequest+0x9c
     84d747df acpi!ACPIBusIrpDeviceUsageNotification+0xf5
     84d2d36c acpi!ACPIDispatchIrp+0xe8
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     817c6a9d nt!ViFilterDispatchPnp+0xe9
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     84fed489 pci!PciCallDownIrpStack+0xbf
     84fde1cb pci!PciDispatchPnpPower+0xdf
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     817c6a9d nt!ViFilterDispatchPnp+0xe9
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     84ff2ff5 pci!PciSendPnpIrp+0xbd
 84fec820 pci!PciDevice_DeviceUsageNotification+0x6e
     84fde1f8 pci!PciDispatchPnpPower+0x10c
 817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     84d76ce2 acpi!ACPIFilterIrpDeviceUsageNotification+0x96
     84d2d36c acpi!ACPIDispatchIrp+0xe8
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     84f7f16c PCIIDEX!PortWdmForwardIrpSynchronous+0x8e
     84f7b2b3 PCIIDEX!GenPnpFdoUsageNotification+0xcb
     84f7d301 PCIIDEX!PciIdeDispatchPnp+0x45
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c

La trace de la pile montre que Acpi.sys essayait de terminer IRP 8f84ef00. Le vérificateur de pilotes a forcé une complétion différée, doncAcpi.sys retourné STATUS_PENDING à pci! PciCallDownIrpStack. Si cet appel avait provoqué un plantage, le propriétaire du pilote aurait besoin de passer en revue le code source pour pci! PciCallDownIrpStack et révisez-le pour gérer correctement les STATUS_PENDING.