Forzare le richieste di I/O in sospeso

L'opzione Force Pending I/O Requests restituisce in modo casuale STATUS_PENDING in risposta alle chiamate di un driver a IoCallDriver. Questa opzione verifica la logica del driver per rispondere a STATUS_PENDING restituire valori da IoCallDriver.

Questa opzione è supportata solo in Windows Vista e versioni successive del sistema operativo Windows.

Attenzione Non usare questa opzione su un driver, a meno che non si disponga di informazioni dettagliate sull'operazione del driver e che il driver sia progettato per gestire STATUS_PENDING restituire valori da tutte le relative chiamate a IoCallDriver. L'esecuzione di questa opzione su un driver non progettato per gestire STATUS_PENDING da tutte le chiamate può causare arresti anomali, danneggiamenti della memoria e comportamento insolito del sistema che può essere difficile da eseguire o correggere.

Perché usare le richieste di I/O in sospeso?

I driver di livello superiore in uno stack di driver chiamano IoCallDriver per passare un'IRP fino a driver di livello inferiore nello stack di driver. La routine di invio del driver nel driver di livello inferiore che riceve l'IRP può completare immediatamente l'IRP o restituire STATUS_PENDING e completare l'IRP in un secondo momento.

In genere, il chiamante deve essere preparato per gestire entrambi i risultati. Tuttavia, poiché la maggior parte delle routine di invio gestisce immediatamente l'IRP, la logica di STATUS_PENDING nel chiamante non viene spesso esercitata e potrebbero non essere rilevati errori di logica gravi. L'opzione Force Pending I/O Requests intercetta le chiamate a IoCallDriver e restituisce STATUS_PENDING per testare la logica usata raramente dal driver chiamante.

Quando si usa Force Pending I/O Requests?

Prima di eseguire questo test, esaminare la progettazione del driver e il codice sorgente e verificare che il driver sia destinato a gestire STATUS_PENDING da tutte le chiamate IoCallDriver .

Molti driver non sono progettati per gestire STATUS_PENDING su tutte le chiamate a IoCallDriver. Potrebbero inviare l'IRP a un determinato driver noto che è garantito di completare immediatamente l'IRP. L'invio di STATUS_PENDING a un driver che non gestisce può causare arresti anomali del sistema e arresto anomalo del sistema e danneggiamento della memoria.

Come devono gestire i driver STATUS_PENDING?

Il driver di livello superiore che chiama IoCallDriver deve gestire un valore restituito STATUS_PENDING come indicato di seguito:

  • Prima di chiamare IoCallDriver, il driver deve chiamare IoBuildSynchronousFsdRequest per organizzare l'elaborazione sincrona dell'IRP.

  • Se IoCallDriver restituisce STATUS_PENDING, il driver deve attendere il completamento dell'IRP chiamando KeWaitForSingleObject nell'evento specificato.

  • Il driver deve prevedere che l'IRP potrebbe essere liberato prima che I/O Manager segnali l'evento.

  • Dopo aver chiamato IoCallDriver, il chiamante non può fare riferimento all'IRP.

Quali errori forzano il rilevamento delle richieste di I/O in sospeso?

L'opzione Force Pending I/O Request rileva gli errori seguenti nel driver che chiama IoCallDriver e riceve un valore restituito STATUS_PENDING:

  • Il driver non chiama IoBuildSynchronousFsdRequest per organizzare l'elaborazione sincrona.

  • Il driver non chiama KeWaitForSingleObject.

  • Il driver fa riferimento a un valore nella struttura IRP dopo aver chiamato IoCallDriver. Dopo aver chiamato IoCallDriver, il driver di livello superiore non può accedere all'IRP a meno che non abbia impostato una routine di completamento e quindi, solo quando tutti i driver di livello inferiore hanno completato l'IRP. Se l'IRP viene liberato, il driver si arresterà in modo anomalo.

  • Il driver chiama in modo errato una funzione correlata. Ad esempio, il driver chiama KeWaitForSingleObject e passa un handle all'evento (come parametro Object ), anziché passare un puntatore a un oggetto evento.

  • Il driver attende l'evento errato. Ad esempio, il driver chiama IoSetCompletionRoutine, ma attende un evento interno segnalato dalla propria routine di completamento, anziché attendere l'evento IRP segnalato da Gestione I/O al termine dell'IRP.

Forzare le modifiche delle richieste di I/O in sospeso introdotte in Windows 7

A partire da Windows 7, l'opzione Force Pending I/O Requests è più efficace per forzare l'esercizio dei percorsi di codice STATUS_PENDING nei driver verificati. Nelle versioni precedenti di Windows, Driver Verifier ha costretto un completamento IRP a essere ritardato solo quando viene eseguito il primo IoCompleteRequest per tale IRP . Ciò significa che l'efficacia della verifica di Driver1 può essere ridotta dal comportamento di Driver2 dallo stesso stack di dispositivi. Driver2 potrebbe attendere in modo sincrono il completamento prima che venga restituito dalla routine di invio a Driver1. Il ritardo forzato del completamento dell'IRP si verifica esattamente prima che la richiesta di I/O venga rimessa nel driver verificato nel percorso di completamento. Ciò significa che il percorso del codice STATUS_PENDING del driver verificato viene effettivamente esercitato e il driver verificato percepisce un ritardo nel completamento.

Attivazione di questa opzione

Per attivare Le richieste di I/O in sospeso, è necessario attivare anche la verifica di I/O. È possibile attivare l'opzione Force Pending I/O Requests per uno o più driver usando Gestione verifica driver o la riga di comando Verifier.exe. Per informazioni dettagliate, vedere Selezione delle opzioni di verifica driver.

L'opzione Force Pending I/O Requests è supportata solo in Windows Vista e nelle versioni successive di Windows.

  • Nella riga di comando

    Per attivare Richieste di I/O in sospeso, usare un valore flag di 0x210 o aggiungere 0x210 al valore del flag. Questo valore attiva la verifica di I/O (0x10) e Forza richieste di I/O in sospeso (0x200).

    Ad esempio:

    verifier /flags 0x210 /driver MyDriver.sys
    

    L'opzione sarà attiva dopo l'avvio successivo.

    Se si tenta di attivare solo Le richieste di I/O in sospeso (verificatore /flags 0x200), Il verificatore driver abilita automaticamente sia La verifica di I/O in sospeso (0x200) sia la verifica di I/O in sospeso.

    È anche possibile attivare e disattivare Le richieste di I/O in sospeso senza riavviare il computer aggiungendo il parametro /volatile al comando. Ad esempio:

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

    Questa impostazione è efficace immediatamente, ma viene persa quando si arresta o si riavvia il computer. Per informazioni dettagliate, vedere Uso delle impostazioni volatili.

  • Uso di Gestione verifica driver

    1. Avviare Gestione verifica driver. Digitare Verifica in una finestra del prompt dei comandi.
    2. Selezionare Crea impostazioni personalizzate (per gli sviluppatori di codice) e quindi fare clic su Avanti.
    3. Selezionare Seleziona singole impostazioni da un elenco completo.
    4. Selezionare Verifica di I/O e Forza richieste di I/O in sospeso.

    Se si seleziona solo Forza richieste di I/O in sospeso, Gestione verifica driver ricorda che la verifica di I/O è necessaria e offre per abilitarla.

Visualizzazione dei risultati

Per visualizzare i risultati del test Force Pending I/O Requests, usare l'estensione del debugger !verifier con un valore flag di 0x40.

Per informazioni sul verificatore !, vedere l'argomento !verifier nella documentazione degli strumenti di debug per Windows .

Se il computer di test si arresta in modo anomalo come risultato del test Force Pending I/O Requests, è possibile usare il comando !verifier 40 per trovare la causa. In una traccia dello stack corrente individuare l'indirizzo dell'IRP usato di recente dal driver. Ad esempio, se si usa il comando kP , che visualizza il frame dello stack per un thread, è possibile trovare l'indirizzo IRP tra i parametri della funzione della traccia dello stack corrente. Eseguire quindi !verifier 40 e cercare l'indirizzo dell'IRP. Le tracce dello stack in sospeso più recenti vengono visualizzate nella parte superiore della visualizzazione.

Ad esempio, la traccia dello stack seguente di Pci.sys mostra la relativa risposta alle richieste di I/O in sospeso. Il test non rivela errori nella logica di 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 traccia dello stack mostra che Acpi.sys stava tentando di completare l'IRP 8f84ef00. Il verificatore driver ha forzato un completamento posticipato, quindiAcpi.sysrestituito STATUS_PENDING a pci! PciCallDownIrpStack. Se questa chiamata aveva causato un arresto anomalo, il proprietario del driver avrebbe bisogno di esaminare il codice sorgente per pci! PciCallDownIrpStack e modificarlo per gestire correttamente il STATUS_PENDING.