Schreiben einer ISR
Treiber für physische Geräte, die Interrupts generieren, müssen mindestens eine Interruptdienstroutine (ISR) aufweisen. Der ISR muss alles tun, was für das Gerät geeignet ist, um den Interrupt zu schließen, einschließlich der Unterbrechung des Geräts. Dann sollte sie nur das tun, was erforderlich ist, um den Zustand zu speichern und einen DPC in die Warteschlange zu stellen, um den E/A-Vorgang mit einer niedrigeren Priorität (IRQL) abzuschließen als die, bei der der ISR ausgeführt wird.
Der ISR eines Treibers wird in einem Interruptkontext bei einer systemseitig zugewiesenen DIRQL ausgeführt, wie vom SynchronizeIrql-Parameter für IoConnectInterruptEx angegeben.
ISRs sind unterbrechbar. Ein anderes Gerät mit einem höheren systemseitig zugewiesenen DIRQL kann jederzeit unterbrechen oder ein High-IRQL-Systemunterbrechung auftreten.
Bevor das System einen ISR aufruft, ruft es die Spinsperre des Interrupts ab, sodass der ISR nicht gleichzeitig auf einem anderen Prozessor ausgeführt werden kann. Nachdem der ISR zurückgegeben wurde, gibt das System die Drehsperre auf.
Da ein ISR mit einem relativ hohen IRQL-Wert ausgeführt wird, der Interrupts mit einem gleichwertigen oder niedrigeren IRQL auf dem aktuellen Prozessor maskiert, sollte die Steuerung so schnell wie möglich zurückgegeben werden. Darüber hinaus schränkt das Ausführen eines ISR bei DIRQL den Satz von Supportroutinen ein, die der ISR aufrufen kann. Weitere Informationen finden Sie unter Verwalten von Hardwareprioritäten.
In der Regel führt ein ISR die folgenden allgemeinen Schritte aus:
Wenn das Gerät, das den Interrupt verursacht hat, nicht vom ISR unterstützt wird, gibt der ISR sofort FALSE zurück.
Andernfalls löscht der ISR den Interrupt bei Bedarf, speichert den erforderlichen Gerätekontext und stellt einen DPC in die Warteschlange, um den E/A-Vorgang bei einer niedrigeren IRQL abzuschließen. Weitere Informationen finden Sie unter DPC-Objekte und DPCs . Der ISR muss dann TRUE zurückgeben.
Insbesondere sollte der ISR bei Treibern, die geräteinterne E/A-Vorgänge nicht überlappen, folgendes ausführen:
Bestimmen Sie, ob der Interrupt falsch ist. Wenn ja, geben Sie sofort FALSE zurück, sodass der ISR des geräts, das unterbrochen wurde, sofort aufgerufen wird. Andernfalls fahren Sie mit der Interruptverarbeitung fort.
Unterbrechen Sie das Gerät bei Bedarf.
Sammeln Sie die Kontextinformationen, die die DpcForIsr-Routine (oder CustomDpc) benötigt, um die E/A-Verarbeitung für den aktuellen Vorgang abzuschließen.
Speichern Sie diesen Kontext in einem Bereich, der für die DpcForIsr - oder CustomDpc-Routine zugänglich ist, normalerweise in der Geräteerweiterung des Zielgeräteobjekts, für das die Verarbeitung der aktuellen E/A-Anforderung den Interrupt verursacht hat.
Wenn sich ein Treiber mit E/A-Vorgängen überschneidet, müssen die Kontextinformationen eine Anzahl der ausstehenden Anforderungen enthalten, die die DPC-Routine ausführen muss, sowie den Kontext, den die DPC-Routine zum Abschließen jeder Anforderung benötigt. Wenn der ISR aufgerufen wird, um einen weiteren Interrupt zu behandeln, bevor der DPC ausgeführt wurde, darf er den gespeicherten Kontext für eine Anforderung, die noch nicht vom DPC abgeschlossen wurde, nicht überschreiben.
Wenn der Treiber über eine DpcForIsr-Routine verfügt, rufen Sie IoRequestDpc mit Zeigern auf das aktuelle IRP, das Zielgerätobjekt und den gespeicherten Kontext auf. IoRequestDpc stellt die DpcForIsr-Routine in die Warteschlange, die ausgeführt werden soll, sobald IRQL auf einem Prozessor unter DISPATCH_LEVEL fällt.
Wenn der Treiber über eine CustomDpc-Routine verfügt, rufen Sie KeInsertQueueDpc mit einem Zeiger auf das DPC-Objekt (der CustomDpc-Routine zugeordnet) und zeiger(en) auf jeden gespeicherten Kontext auf, den die CustomDpc-Routine zum Abschließen des Vorgangs benötigt. In der Regel übergibt der ISR auch Zeiger an das aktuelle IRP und das Zielgerätobjekt. Die CustomDpc-Routine wird ausgeführt, sobald IRQL unter DISPATCH_LEVEL auf einem Prozessor fällt.
Geben Sie TRUE zurück, um anzugeben, dass das Gerät den Interrupt generiert hat.
Im Allgemeinen führt eine ISR keine tatsächliche E/A-Verarbeitung durch, um eine IRP zu erfüllen. Stattdessen wird die Unterbrechung des Geräts verhindert, die erforderlichen Zustandsinformationen eingerichtet und der DpcForIsr oder CustomDpc des Treibers in die Warteschlange gestellt, um die E/A-Verarbeitung durchzuführen, die erforderlich ist, um die aktuelle Anforderung zu erfüllen, die zur Unterbrechung des Geräts geführt hat.
Ein ISR muss für das kürzeste mögliche Intervall bei DIRQL ausgeführt werden. Die Durchführung dieser Richtlinie erhöht den E/A-Durchsatz für jedes Gerät auf dem Computer, da die Ausführung bei DIRQL alle Interrupts maskiert, denen das System einen geringeren oder gleichen IRQL-Wert zugewiesen hat.
Die SynchronizeIrql der Interruptobjekte des Treibers, die beim Namen des Treibers IoConnectInterrupt angegeben wird, bestimmt die DIRQL, bei der der ISR des Treibers ausgeführt wird. Weitere Informationen finden Sie unter Synchronisieren des Zugriffs auf Gerätedaten.