Punti da considerare quando si annullano i runtime di integrazione

Questa sezione illustra le linee guida per l'implementazione di una routine Cancel e la gestione di irP annullabili. Per altre informazioni sulla gestione dei runtime di integrazione annullabili, vedere Flow of Control for Cancel-Safe IRP Queuing.

Linee guida generali per tutte le routine di annullamento

Il gestore di I/O mantiene il blocco di selezione annulla ogni volta che chiama la routine Cancel di un driver. Di conseguenza, ogni routine Cancel deve:

  • Chiama IoReleaseCancelSpinLock prima di restituire il controllo.

  • Non chiamare IoAcquireCancelSpinLock a meno che non chiami prima IoReleaseCancelSpinLock .

  • Effettuare una chiamata reciproca a IoReleaseCancelSpinLock per ogni chiamata eseguita a IoAcquireCancelSpinLock.

Ogni volta che la routine Cancel chiama IoReleaseCancelSpinLock, deve passare l'IRQL restituito dalla chiamata più recente a IoAcquireCancelSpinLock. Quando si rilascia il blocco spin acquisito dal gestore di I/O (e mantenuto quando è stata chiamata la routine Cancel), la routine Cancel deve passare Irp-CancelIrql>.

Un driver non deve chiamare routine esterne (ad esempio IoCompleteRequest) tenendo premuto un blocco di rotazione perché può verificarsi un deadlock.

Uso della coda definita da Gestione I/O

A meno che un driver non gestisca le proprie code interne di provider di integrazione, la routine Cancel viene chiamata con un IRP in ingresso che potrebbe essere uno dei seguenti:

  • CurrentIrp nell'oggetto dispositivo di destinazione di input

  • Voce nella coda del dispositivo associata all'oggetto dispositivo di destinazione

A meno che un driver non gestisca le proprie code interne di runtime di integrazione, la routine Cancel deve chiamare KeRemoveEntryDeviceQueue con l'IRP di input per verificare se si tratta di una voce nella coda del dispositivo associata all'oggetto dispositivo di destinazione. La routine Cancel del driver non può chiamare KeRemoveDeviceQueue o KeRemoveByKeyDeviceQueue perché non può presupporre che l'IRP specificato si trova in una posizione specifica nella coda del dispositivo.

Stato corrente dell'IRP di input

Se viene chiamata una routine Cancel con un IRP per il quale il driver ha già avviato l'elaborazione di I/O e la richiesta verrà completata a breve, la routine Cancel dovrebbe rilasciare il blocco spin di annullamento del sistema e il controllo restituito.

Se lo stato corrente dell'IRP di input è In sospeso, una routine Cancel deve eseguire le operazioni seguenti:

  1. Impostare il blocco di stato di I/O di input IRP con STATUS_CANCELLED per Stato e zero per Informazioni.

  2. Rilascia tutti i blocchi di rotazione che mantiene, incluso il blocco spin di annullamento del sistema.

  3. Chiamare IoCompleteRequest con l'IRP specificato.

Mantenimento di irP in uno stato annullabile

Qualsiasi routine driver che contiene un IRP in uno stato annullabile deve chiamare IoMarkIrpPending e deve chiamare IoSetCancelRoutine per impostare il relativo punto di ingresso per la routine Cancel in IRP. Solo allora la routine del driver può chiamare routine di supporto aggiuntive, ad esempio IoStartPacket, IoAllocateController o ExInterlockedInsert. Routine elenco .

Qualsiasi routine del driver che successivamente elabora irP annullabili deve verificare se un IRP è già stato annullato prima che inizi le operazioni per soddisfare la richiesta. La routine deve chiamare IoSetCancelRoutine per reimpostare il relativo punto di ingresso per la routine Cancel su NULL in IRP. Solo in questo caso la routine può iniziare l'elaborazione di I/O per l'IRP di input.

Una routine potrebbe dover reimpostare il punto di ingresso per una routine Cancel in un IRP anche se è in grado di passare irP per un'ulteriore elaborazione da parte di altre routine del driver e tali irP potrebbero essere mantenuti in uno stato annullabile.

Qualsiasi driver di livello superiore che contiene un IRP in uno stato annullabile deve reimpostare il punto di ingresso Annulla su NULL prima di passare l'IRP al driver inferiore successivo con IoCallDriver.

Annullamento di un IRP

Qualsiasi driver di livello superiore può chiamare IoCancelIrp con un IRP allocato e passato per un'ulteriore elaborazione da parte di driver di livello inferiore. Tuttavia, tale driver non può presupporre che l'IRP specificato verrà completato con STATUS_CANCELLED da driver inferiori.

Sincronizzazione

Un driver può (o deve, a seconda della progettazione) mantenere informazioni aggiuntive sullo stato nell'estensione del dispositivo per tenere traccia dello stato annullabile dei provider di integrazione. Se questo stato è condiviso dalle routine del driver in esecuzione in IRQL <= DISPATCH_LEVEL, i dati condivisi devono essere protetti con un blocco di selezione allocato e inizializzato del driver.

Il driver deve gestire con attenzione le acquisizioni e le versioni del blocco spin di annullamento del sistema e i propri blocchi di rotazione. Deve contenere il blocco spin di annullamento del sistema per gli intervalli più brevi possibili. Prima di accedere a un IRP annullabile, tale driver deve sempre controllare il valore restituito di IoSetCancelRoutine per determinare se la routine Cancel è già in esecuzione (o sta per essere eseguita); in tal caso, dovrebbe consentire alla routine Cancel di completare l'IRP.

Se un driver di dispositivo mantiene le informazioni sullo stato relative ai runtime di integrazione annullabili condivisi da varie routine driver con il relativo ISR, queste altre routine devono sincronizzare l'accesso allo stato condiviso con l'ISR. Solo una routine SynchCritSection fornita dal driver può accedere alle informazioni sullo stato condivise con l'ISR in modo sicuro per più processi.

Per altre informazioni, vedere Tecniche di sincronizzazione.