Commutateurs IRQL et Thread / Context de pilote de périphérique

Je suis nouveau pour la programmation de pilotes de périphériques Windows. Je sais que certaines opérations ne peuvent être effectuées qu’à IRQL PASSIVE_LEVEL . Par exemple, Microsoft dispose de cet exemple de code pour écrire dans un fichier à partir d’un pilote de kernel:

 if (KeGetCurrentIrql() != PASSIVE_LEVEL) return STATUS_INVALID_DEVICE_STATE; Status = ZwCreateFile(...); 

Ma question est la suivante: Qu’est-ce qui empêche l’IRQL d’être généré après la KeGetCurrentIrql() ci-dessus? Disons qu’un contexte ou un swithch de thread se produit, l’IRQL ne pourrait-elle pas soudainement être DISPATCH_LEVEL quand il reviendrait à mon pilote, ce qui entraînerait alors un blocage du système?

Si ce n’est PAS possible, pourquoi ne pas simplement vérifier l’IRQL dans la fonction DriverEntry et en avoir terminé une fois pour toutes?

L’irql d’un thread ne peut être soulevé que par lui-même.

Étant donné que vous êtes appelé par les pilotes supérieurs / inférieurs, l’irql du contexte en cours d’exécution peut être différent. Et il y a quelques fonctions qui augmentent / diminuent l’irql.

Quelques exemples:

IRP_MJ_READ

  NTSTATUS DispatchRead( __in struct _DEVICE_OBJECT *DeviceObject, __in struct _IRP *Irp ) { // this will be called at irql == PASSIVE_LEVEL ... // we have acquire a spinlock KSSPIN_LOCK lck; KeInititializeSpinLock( &lck ); KIRQL prev_irql; KeAcquireSpinLock( &lck,&prev_irql ); // KeGetCurrentIrql() == DISPATCH_LEVEL KeReleaseSpinLock( &lck, prev_irql ); // KeGetCurrentIrql() == PASSIVE_LEVEL ... } 

Les routines d’achèvement peuvent être appelées à DISPATCH_LEVEL et doivent donc se comporter en conséquence.

 NTSTATUS CompleteSth(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context) { // KeGetCurrentIrql() >= PASSIVE_LEVEL } 

L’IRQL peut uniquement changer de manière significative sous votre contrôle en le définissant. Il existe deux IRQL “spécifiques aux threads” – PASSIVE_LEVEL et APC_LEVEL. Vous contrôlez l’entrée et la sortie de ces niveaux avec des choses comme les mutex rapides, et un changement de contexte à votre thread vous laissera toujours au niveau où vous étiez avant. Ci-dessus, il y a des IRQL “spécifiques au processeur”. C’est DISPATCH_LEVEL ou supérieur. Dans ces niveaux, un changement de contexte ne peut pas avoir lieu. Vous entrez dans ces niveaux en utilisant des verrous de rotation et autres. Les ISR se produiront à des IRQL plus élevées sur votre thread, mais vous ne pouvez pas les voir. Lorsqu’ils vous rendent le contrôle, votre IRQL est restaurée.

DriverEntry est également appelé à PASSIVE_LEVEL.

Si vous voulez faire un travail à PASSIVE_LEVEL, utilisez des fonctions comme IoQueueWorkItem