Condividi tramite


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 testa la logica del driver nel rispondere ai valori di ritorno STATUS_PENDING da IoCallDriver.

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

Cautela Non usare questa opzione su un driver a meno che non si abbia una conoscenza dettagliata del funzionamento 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 Forza richieste di I/O in sospeso?

I driver di livello superiore in uno stack di driver chiamano IoCallDriver per passare un IRP ai driver di livello inferiore nello stesso stack. 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.The driver dispatch routine in the lower-level driver that receives the IRP can either complete the IRP immediately or return STATUS_PENDING and complete the IRP at a later time.

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

Quando si usa Forzare le richieste di I/O in sospeso?

Prima di eseguire questo test, esaminare la progettazione del driver e il codice sorgente, e confermare che il driver è progettato per gestire STATUS_PENDING da tutte le sue 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 lo gestisce può causare arresti anomali del driver e del sistema e possibile 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 di IRP.

  • Se IoCallDriver restituisce STATUS_PENDING, il driver deve chiamare KeWaitForSingleObject sull'evento specificato per attendere il completamento dell'IRP.

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

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

Quali errori vengono rilevati da Force Pending I/O Request?

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 a 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 erroneamente 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, invece di attendere l'evento IRP segnalato da Gestione I/O al termine dell'IRP.

Forzare le richieste di I/O in sospeso: modifiche 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 provocava il ritardo dell'elaborazione di un completamento IRP solo quando veniva 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 dispatch a Driver1. Il ritardo forzato nel completamento dell'IRP si verifica esattamente prima che la richiesta di I/O ritorni nel driver certificato lungo il 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.

l'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 Forza richieste di I/O in sospeso per uno o più driver, utilizzando Gestione Verifica Driver o il comando Verifier.exe. Per informazioni dettagliate, vedere Selezione delle Opzioni del Verificatore Driver.

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

  • Alla riga di comando

    Per attivare Forzare le richieste di I/O in sospeso, utilizzare un valore di flag di 0x210 o aggiungere 0x210 al valore attuale del flag. Questo valore attiva la verifica di I/O (0x10) e forza le richieste di I/O in sospeso (0x200).

    Per esempio:

    verifier /flags 0x210 /driver MyDriver.sys
    

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

    Se si tenta di attivare solo Force Pending I/O Requests (verifier /flags 0x200), Driver Verifier abilita automaticamente sia Force Pending I/O Requests (0x200) che I/O Verification.

    È anche possibile attivare e disattivare Force Pending I/O Requests senza riavviare il computer aggiungendo il parametro /volatile al comando. Per esempio:

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

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

  • Uso del Driver Verifier Manager

    1. Avviare il Manager verifica driver. Digitare Verifier in una finestra del Prompt dei Comandi.
    2. Selezionare Crea impostazioni personalizzate (per sviluppatori di codice) e quindi fare clic su Avanti.
    3. Selezionare Selezionare le singole impostazioni da un elenco completo.
    4. Selezionare Verifica I/O e Forzare richieste di I/O in sospeso.

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

Visualizzazione dei risultati

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

Per informazioni su !verifier, vedere l'argomento !verifier nella documentazione relativa agli strumenti di debug per Windows .

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

Ad esempio, l'analisi dello stack seguente di Pci.sys mostra la risposta a Force Pending I/O Requests .For example, the following stack trace of Pci.sys shows its response to Force Pending I/O Requests. 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

L'analisi dello stack mostra che Acpi.sys stava tentando di completare IRP 8f84ef00. Driver Verifier ha forzato un completamento posticipato, quindi Acpi.sys ha restituito STATUS_PENDING a pci! PciCallDownIrpStack. Se questa chiamata avesse causato un arresto anomalo, il proprietario del driver dovrà esaminare il codice sorgente per pci. PciCallDownIrpStack e modificarlo per gestire correttamente il STATUS_PENDING.