MmLockPagableCodeSection-Makro (wdm.h)

Die MmLockPagableCodeSection-Routine sperrt einen Abschnitt des Treibercodes, der eine Reihe von Treiberroutinen enthält, die mit einer speziellen Compilerdirektive gekennzeichnet sind, in den Systemraum.

Syntax

void MmLockPagableCodeSection(
  [in]  Address
);

Parameter

[in] Address

Gibt eine symbolische Adresse an. Diese Adresse ist in der Regel der Name einer Treiberfunktion in einem Abschnitt des Treibercodes, der mit #pragma alloc_text (PAGExxxx, driverfunction) gekennzeichnet wurde. Alle Funktionen im Abschnitt PAGExxxx werden dann garantiert gesperrt, wenn diese Funktion zurückgegeben wird.

Rückgabewert

Keine

Bemerkungen

MmLockPagableCodeSection gibt einen undurchsichtigen Wert zurück, den das Betriebssystem verwendet, um diesen Abschnitt des Treibercodes zu identifizieren. Dieser undurchsichtige Wert kann anschließend an MmLockPagableSectionByHandle (wenn der Treiber den Abschnitt entsperrt und später erneut sperrt) oder an MmUnlockPagableImageSection übergeben werden.

Die MmLockPagableCodeSection-Routine und MmUnlockPagableImageSection (die Routine, die die entgegengesetzte Aktion ausführt) unterstützen Treiber, die die folgenden Aktionen ausführen können:

  • Verschieben Sie das Laden einer Teilmenge von Treiberroutinen in den residenten Arbeitsspeicher, bis eingehende E/A-Anforderungen für die Geräte des Treibers die Verarbeitung von IRPs durch diese Routinen erforderlich machen.

  • Stellen Sie dieselbe Teilmenge der Treiberroutinen für das Auslagern zur Verfügung, wenn sie die Verarbeitung von E/A-Anforderungen abgeschlossen haben und derzeit keine zusätzlichen Anforderungen für die Geräte des Treibers erwartet werden.

MmLockPagableCodeSection, MmLockPagableSectionByHandle und MmUnlockPagableImageSection sind für die Verwendung durch Geräte- und Zwischentreiber vorgesehen, die die folgenden Eigenschaften aufweisen:

  • Der Treiber verfügt über Codepfade, die möglicherweise nicht benötigt werden, während das System ausgeführt wird. Wenn sie jedoch benötigt werden, muss der Treibercode resident sein, da er in einem beliebigen Threadkontext oder unter IRQL >= DISPATCH_LEVEL ausgeführt wird.

  • Der Treiber kann genau bestimmen, wann die auslagerungsfähigen Routinen geladen werden sollen und wann sie wieder ausgelagert werden können.

Der vom System bereitgestellte fehlertolerante Datenträgertreiber unterstützt beispielsweise die Erstellung von Spiegel-, Stripe- und Volumesätzen. Ein bestimmter Computer kann jedoch nur mit einem Spiegel-Satz, nur mit einem Stripe-Satz, nur mit einem Volume-Satz oder mit einer beliebigen Kombination dieser drei möglichen Optionen konfiguriert werden. Unter diesen Umständen reduziert der Ftdisk-Systemtreiber die Größe des geladenen Images, indem Routinen markiert werden, die explizit Spiegel-, Stripe- und Volumesätze unterstützen, die zu auslagerungsfähigen Codeabschnitten gehören. Während der Treiberinitialisierung werden auslagerungsfähige Codeabschnitte nur dann als resident festgelegt, wenn der Benutzer die Datenträger so konfiguriert hat, dass Spiegel,Stripe- oder Volumesätze vorhanden sind. Wenn der Benutzer die Datenträger dynamisch neu partitioniert, sperrt der ftdisk-Treiber alle zusätzlichen auslagerungsfähigen Codeabschnitte, die erforderlich sind, um alle vom Benutzer angeforderten Spiegel-, Stripe- oder Volumesätze zu unterstützen.

Als andere Beispiele verfügen die vom System bereitgestellten seriellen und parallelen Treiber über DispatchCreate - und DispatchClose-Routinen , die aufgerufen werden, wenn ein bestimmter Port für exklusive E/A-Vorgänge geöffnet wird und wenn der Handle für einen geöffneten Port freigegeben wird. Serielle und parallele E/A-Anforderungen sind jedoch sporadisch und bestimmen, welche Anwendungen der Endbenutzer derzeit ausführt und welche Anwendungsoptionen der Endbenutzer derzeit ausübt. Unter diesen Umständen reduzieren die seriellen und parallelen Systemtreiber die Größe ihrer geladenen Images, indem sie viele Routinen als teil eines ausseitigen Codeabschnitts markieren, den die DispatchCreate-Routine nur dann als resident macht, wenn der erste Port für E/A geöffnet wird.

Beachten Sie, dass jeder der vorherigen Systemtreiber beide Kriterien für auslagerungsfähige Abschnitte erfüllt: Der Treiber verfügt über Codepfade, die möglicherweise nicht benötigt werden, während das System ausgeführt wird, und der Treiber kann genau bestimmen, wann sein auslagerungsfähiger Abschnitt geladen werden soll und wieder ausgelagert werden kann.

Da es sich um einen kostspieligen Vorgang handelt, einen Abschnitt zu sperren, verwenden Sie MmLockPagableCodeSection für die erste Anforderung, wenn ein Treiber einen auslagerungsfähigen Codeabschnitt an mehreren Stellen sperrt. Stellen Sie nachfolgende Sperranforderungen, indem Sie MmLockPagableSectionByHandle aufrufen und das von MmLockPagableCodeSection zurückgegebene Handle übergeben. Das Sperren nach Handle verbessert die Treiberleistung erheblich, da der Speicher-Manager den undurchsichtigen Rückgabewert verwendet, um den relevanten Abschnitt schnell zu finden, anstatt eine geladene Modulliste zu durchsuchen. Ein gesperrter Abschnitt wird durch Aufrufen von MmUnlockPagableImageSection entsperrt.

Jede Treiberroutine in einem auslagerungsfähigen Codeabschnitt muss mit der folgenden Compilerdirektive gekennzeichnet sein:

#pragma alloc_text(PAGExxxx, DriverRoutine)

wobei xxxx ein optionaler vierstelliger eindeutiger Bezeichner für den auslagerungsfähigen Abschnitt des Aufrufers ist und DriverRoutine ein Einstiegspunkt ist, der in den auslagerungsfähigen Codeabschnitt eingeschlossen werden soll. Bei der Schlüsselwort (keyword) PAGE und dem vom Treiber bestimmten Suffix, das bis zu vier Zeichen lang sein kann, muss die Groß-/Kleinschreibung beachtet werden. Das heißt, PAGE muss groß geschrieben werden.

Ein einzelner Aufruf von MmLockPagableCodeSection in z. B. der DispatchCreate-Routine eines Treibers bewirkt, dass der gesamte Abschnitt, der jede Treiberroutine enthält, die mit demselben PAGExxxx-Bezeichner gekennzeichnet ist, im Systembereich gesperrt wird.

Bestimmte Typen von Treiberroutinen können nicht in den ausserstellbaren Abschnitt eines Treibers eingeschlossen werden, einschließlich der folgenden:

  • Machen Sie niemals eine ISR-Seite verfügbar. Es ist möglich, dass ein Gerätetreiber einen falschen Interrupt erhält, auch wenn sein Gerät nicht verwendet wird, insbesondere wenn der Interruptvektor freigegeben werden könnte. Im Allgemeinen sollte ein ISR nicht ausgelagert werden, auch wenn ein Treiber Interrupts auf seinem Gerät explizit deaktivieren kann.

  • Machen Sie eine DPC-Routine niemals auslagerungsfähig, wenn der Treiber nicht steuern kann, wann der DPC in die Warteschlange gestellt wird, z. B. eine DpcForIsr - oder CustomDpc-Routine , die von einer ISR aus in die Warteschlange gestellt werden könnte. Im Allgemeinen sollten Treiberroutinen, die mit IRQL >= DISPATCH_LEVEL ausgeführt werden und die in einem beliebigen Threadkontext oder als Reaktion auf ein zufälliges externes Ereignis aufgerufen werden können, nicht ausgelagert werden.

  • Machen Sie die DispatchRead - oder DispatchWrite-Routine niemals in einem Treiber auslagerungsfähig, der Teil des E/A-Pfads des Systempapageings sein könnte. Der Treiber eines Datenträgers, der möglicherweise die Systemseitendatei enthalten kann, muss über DispatchRead - und DispatchWrite-Routinen verfügen, die während der Ausführung des Systems vorhanden sind, ebenso wie alle Treiber, die über einem solchen Datenträgertreiber liegen.

Beachten Sie, dass Routinen in einem auslagerungsfähigen Abschnitt, der mit der Compilerdirektive #pragma alloc_text(PAGExxxx, ...) gekennzeichnet ist, von Routinen abweichen, die mit der Compilerdirektive #pragma alloc_text(INIT, ...) gekennzeichnet sind. Die Routinen im INIT-Abschnitt sind nicht auslagerungsfähig und werden verworfen, sobald der Treiber von seiner DriverEntry - oder Seiner Reinitialisierungsroutine zurückkehrt, falls er über eine verfügt.

Der Speicher-Manager verwaltet eine interne Sperranzahl für den auslagerungsfähigen Abschnitt eines Treibers. Aufrufe von MmLockPagableCodeSection erhöhen diese Anzahl, und die gegenseitige MmUnlockPagableImageSection erhöht die Anzahl. Der auslagerungsfähige Abschnitt eines Treibers kann nicht ausgelagert werden, es sei denn, diese Anzahl ist 0.

Weitere Informationen zum Erstellen von Auslagerungscodeabschnitten finden Sie unter Auslagerung von Treibern.

Anforderungen

Anforderung Wert
Zielplattform Desktop
Header wdm.h (einschließlich Wdm.h, Ntddk.h, Ntifs.h)
Bibliothek NtosKrnl.lib
DLL NtosKrnl.exe
IRQL <=APC_LEVEL

Weitere Informationen

MmLockPagableDataSection

MmLockPagableSectionByHandle

MmPageEntireDriver

MmResetDriverPaging

MmUnlockPagableImageSection