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 innerhalb eines Abschnitts des Treibercodes, der mit etwas wie #pragma alloc_text (PAGExxxx, Driverfunction)gekennzeichnet wurde. Alle Funktionen im PAGExxxx Abschnitt werden dann garantiert gesperrt, wenn diese Funktion zurückgegeben wird.
Rückgabewert
Nichts
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- übergeben werden (wenn der Treiber den Abschnitt entsperrt und dann später erneut sperrt) oder an MmUnlockPagableImageSection.
Die MmLockPagableCodeSection Routine und MmUnlockPagableImageSection (die Routine, die die entgegengesetzte Aktion ausführt) unterstützen Treiber, die folgende Aktionen ausführen können:
Verzögern Sie das Laden einer Teilmenge von Treiberroutinen in den residenten Speicher, bis eingehende E/A-Anforderungen für die Geräte des Treibers erforderlich sind, damit diese Routinen IRPs verarbeiten können.
Stellen Sie dieselbe Teilmenge von Treiberroutinen für das Ausblättern zur Verfügung, wenn sie die Verarbeitung von E/A-Anforderungen abgeschlossen haben und keine zusätzlichen Anforderungen für die Geräte des Treibers derzeit erwartet werden.
MmLockPagableCodeSection, MmLockPagableSectionByHandle und MmUnlockPagableImageSection sind für die Verwendung durch Geräte- und Zwischentreiber vorgesehen, die die folgenden Merkmale aufweisen:
Der Treiber verfügt über Codepfade, die möglicherweise nicht benötigt werden, während das System ausgeführt wird, aber falls erforderlich, muss der Code des Treibers vorhanden sein, da er in einem beliebigen Threadkontext oder bei IRQL >= DISPATCH_LEVEL ausgeführt wird.
Der Treiber kann genau bestimmen, wann die ausgelagerten Routinen geladen werden sollen und wann sie erneut ausgelagert werden können.
Beispielsweise unterstützt der vom System bereitgestellte fehlertolerante Datenträgertreiber die Erstellung von Spiegelsätzen, Stripesätzen und Volumesätzen. Ein bestimmter Computer kann jedoch nur mit einem Spiegelsatz konfiguriert werden, nur mit einem Streifensatz, nur mit einem Volumesatz oder mit einer Kombination dieser drei möglichen Optionen. Unter diesen Umständen reduziert der Ftdisk-Treiber die Größe des geladenen Bilds, indem Routinen markiert werden, die Spiegel-, Stripe- und Volumesätze explizit unterstützen, die zu seitenfähigen Codeabschnitten gehören. Während der Treiberinitialisierung werden seitenfähige Codeabschnitte nur dann resident, 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 ausserseitigen Codeabschnitte, die erforderlich sind, um alle Spiegel-, Stripe- oder Volumesätze zu unterstützen, die der Benutzer anfordert.
Wie andere Beispiele haben die vom System bereitgestellten seriellen und parallelen Treiber DispatchCreate und DispatchClose Routinen, die aufgerufen werden, wenn ein bestimmter Port für exklusive E/A geöffnet wird, bzw. wenn der Handle für einen geöffneten Port freigegeben wird. Serielle und parallele E/A-Anforderungen sind jedoch sporadisch, bestimmt, welche Anwendungen der Endbenutzer derzeit ausführt und welche Anwendungsoptionen der Endbenutzer derzeit ausführt. Unter diesen Umständen verringern die seriellen und parallelen Treiber des Systems die Größe ihrer geladenen Bilder, indem viele Routinen als ausgelagerter Codeabschnitt markiert werden, den die DispatchCreate Routine nur dann aufgibt, wenn der erste Port für E/A geöffnet wird.
Beachten Sie, dass jeder der vorherigen Systemtreiber beide Kriterien für die Verwendung von seitenfähigen Abschnitten 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 ausgelagerter Abschnitt geladen werden soll und erneut ausgelagert werden kann.
Da es sich um einen kostspieligen Vorgang handelt, um einen Abschnitt zu sperren, verwenden Sie MmLockPagableCodeSection- für die erste Anforderung, wenn ein Treiber einen ausgelagerten Codeabschnitt an mehreren Stellen sperrt. Führen Sie nachfolgende Sperranforderungen durch Aufrufen von MmLockPagableSectionByHandle Übergeben des von MmLockPagableCodeSectionzurückgegebenen Handle aus. Das Sperren durch 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 MmUnlockPagableImageSectionentsperrt.
Jede Treiberroutine in einem ausgelagerten Codeabschnitt muss mit der folgenden Compilerdirektive gekennzeichnet werden:
#pragma alloc_text(PAGExxxx, DriverRoutine)
Dabei ist xxxx ein optionaler vierstelliger, eindeutiger Bezeichner für den seitenfähigen Abschnitt des Aufrufers und DriverRoutine- ein Einstiegspunkt, der in den ausgelagerten Codeabschnitt aufgenommen werden soll. Das Schlüsselwort PAGE und das treiberbestimmte Suffix, das bis zu vier Zeichen umfassen kann, beachten die Groß-/Kleinschreibung; d. h. PAGE- muss großgeschrieben werden.
Ein einzelner Aufruf MmLockPagableCodeSection- in, z. B. die DispatchCreate Routine eines Treibers, bewirkt, dass der gesamte Abschnitt mit jeder Treiberroutine, die mit demselben PAGExxxx Bezeichner gekennzeichnet ist, im Systembereich gesperrt wird.
Bestimmte Arten von Treiberroutinen können nicht teil des seitenfähigen Abschnitts eines Treibers sein, einschließlich der folgenden:
Machen Sie niemals eine ISR-Seite aus. Es ist möglich, dass ein Gerätetreiber einen spurhaften 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 seitenfähig gemacht werden, auch wenn ein Treiber Unterbrechungen auf seinem Gerät explizit deaktivieren kann.
Machen Sie niemals eine DPC-Routineseite verfügbar, wenn der Treiber nicht steuern kann, wann der DPC in die Warteschlange gestellt wird, z. B. DpcForIsr- oder CustomDpc-routine, die von einem ISR in die Warteschlange gestellt werden kann. Im Allgemeinen sollten Treiberroutinen, die bei 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 seitenfähig gemacht werden.
Stellen Sie niemals die DispatchRead- oder DispatchWrite Routineseite in jedem Treiber bereit, der Teil des System paging-E/A-Pfads sein kann. Der Treiber eines Datenträgers, der die Systemseitendatei enthalten kann, muss DispatchRead- und DispatchWrite Routinen aufweisen, die während der Ausführung des Systems vorhanden sind, wie alle Treiber, die über einem solchen Datenträgertreiber überschichtet sind.
Beachten Sie, dass Routinen in einem durch die Compilerdirektive gekennzeichneten Abschnitt #pragma alloc_text(PAGExxxx, ...) von Routinen abweichen, die mit der Compilerdirektive #pragma alloc_text(INIT, ...)gekennzeichnet sind. Die Routinen im abschnitt INIT sind nicht seitenfähig und werden verworfen, sobald der Treiber von seinem DriverEntry- oder seiner Reinitialisieren Routine zurückgibt, sofern vorhanden.
Der Speicher-Manager verwaltet eine interne Sperranzahl für den seitenfähigen Abschnitt eines Treibers. Aufrufe an MmLockPagableCodeSection diese Anzahl erhöhen und die gegenseitigen MmUnlockPagableImageSection die Anzahl erhöht. Der ausgelagerte Abschnitt eines Treibers ist nicht verfügbar, um ausgelagert zu werden, es sei denn, diese Anzahl ist null.
Weitere Informationen zum Erstellen von ausgelagerten Codeabschnitten finden Sie unter Making Drivers Pageable.For more information about creating pageable code sections, see Making Drivers Pageable.
Anforderungen
Anforderung | Wert |
---|---|
Zielplattform- | Desktop |
Header- | wdm.h (include Wdm.h, Ntddk.h, Ntifs.h) |
Library | NtosKrnl.lib |
DLL- | NtosKrnl.exe |
IRQL- | <=APC_LEVEL |