ExInitializeLookasideListEx-Funktion (wdm.h)
Die ExInitializeLookasideListEx-Routine initialisiert eine Lookaside-Liste.
Syntax
NTSTATUS ExInitializeLookasideListEx(
[out] PLOOKASIDE_LIST_EX Lookaside,
[in, optional] PALLOCATE_FUNCTION_EX Allocate,
[in, optional] PFREE_FUNCTION_EX Free,
[in] POOL_TYPE PoolType,
[in] ULONG Flags,
[in] SIZE_T Size,
[in] ULONG Tag,
[in] USHORT Depth
);
Parameter
[out] Lookaside
Ein Zeiger auf die zu initialisierende LOOKASIDE_LIST_EX-Struktur. Bei der Rückgabe beschreibt diese Struktur eine leere Suchliste. Der Aufrufer muss für diese Struktur einen nicht ausgelagerten Systemspeicher verwenden, unabhängig davon, ob die Einträge in der Lookaside-Liste aus ausgelagertem oder nicht ausgelagertem Speicher zugeordnet werden. Auf 64-Bit-Plattformen muss diese Struktur 16-Byte ausgerichtet sein.
[in, optional] Allocate
Ein Zeiger auf eine vom Aufrufer bereitgestellte LookasideListAllocateEx-Routine , die einen neuen Lookaside-list-Eintrag zuordnet. Die ExAllocateFromLookasideListEx-Routine ruft diese LookasideListAllocateEx-Routine auf, wenn die Lookaside-Liste leer ist (enthält keine Einträge). Dieser Parameter ist optional und kann als NULL angegeben werden, wenn keine benutzerdefinierte Zuordnungsroutine erforderlich ist. Wenn dieser Parameter NULL ist, ordnen Aufrufe von ExAllocateFromPagedLookasideList automatisch den ausgelagerten oder nicht ausgelagerten Speicher (wie vom PoolType-Parameter bestimmt) für die neuen Einträge zu.
[in, optional] Free
Ein Zeiger auf eine vom Aufrufer bereitgestellte LookasideListFreeEx-Routine , die einen zuvor zugeordneten Lookaside-list-Eintrag freigibt. Die ExFreeToPagedLookasideList-Routine ruft diese LookasideListFreeEx-Routine auf, wenn die Lookaside-Liste voll ist (das heißt, die Liste enthält bereits die maximale Anzahl von Einträgen, wie vom Betriebssystem festgelegt). Dieser Parameter ist optional und kann als NULL angegeben werden, wenn keine benutzerdefinierte Zuordnungsroutine erforderlich ist. Wenn dieser Parameter NULL ist, geben Aufrufe von ExFreeToPagedLookasideList automatisch den Speicher für die angegebenen Einträge frei.
[in] PoolType
Gibt den Pooltyp der Einträge in der Suchliste an. Legen Sie diesen Parameter auf einen gültigen POOL_TYPE-Enumerationswert fest.
[in] Flags
Gibt einen optionalen Flagwert an, um das Standardverhalten der LookasideListAllocateEx-Routine zu ändern. Legen Sie diesen Parameter auf null oder auf eines der folgenden EX_LOOKASIDE_LIST_EX_FLAGS_XXX-Flagbits fest.
Flag-Bit | BESCHREIBUNG |
---|---|
EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL | Wenn die Zuordnung fehlschlägt, lösen Sie eine Ausnahme aus. |
EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE | Wenn die Zuordnung fehlschlägt, geben Sie NULL zurück, anstatt eine Ausnahme auszugeben. Dieses Flag ist für die Verwendung mit einer Zuordnungsroutine wie ExAllocatePoolWithQuotaTag vorgesehen, die Kontingente für die Poolnutzung berechnet. |
Diese beiden Flagbits schließen sich gegenseitig aus.
Wenn AllocateNULL ist, legen Sie Flags entweder auf null oder EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL fest, aber nicht auf EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE. Andernfalls ist das Verhalten der Standardzuordnungsroutine nicht definiert.
Wenn Flags = EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL, ist der PoolType-Parameterwert bitweise oRed mit dem POOL_RAISE_IF_ALLOCATION_FAILURE Flagbit, um den PoolType-Parameterwert zu bilden, der an die LookasideListAllocateEx-Routine übergeben wird. Die LookasideListAllocateEx-Routine kann diesen PoolType-Wert ohne Änderung an die ExAllocatePoolWithTag-Routine übergeben. Weitere Informationen zum POOL_RAISE_IF_ALLOCATION_FAILURE-Flag finden Sie unter ExAllocatePoolWithTag.
Wenn Flags = EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE, ist der PoolType-Parameterwert bitweise oRed mit dem POOL_QUOTA_FAIL_INSTEAD_OF_RAISE Flagbit, um den PoolType-Parameterwert zu bilden, der an die LookasideListAllocateEx-Routine übergeben wird. Die LookasideListAllocateEx-Routine kann diesen PoolType-Wert ohne Änderung an die ExAllocatePoolWithQuotaTag-Routine übergeben. Weitere Informationen zum POOL_QUOTA_FAIL_INSTEAD_OF_RAISE-Flag finden Sie unter ExAllocatePoolWithQuotaTag.
[in] Size
Gibt die Größe jedes Eintrags in der Suchliste in Bytes an.
[in] Tag
Gibt das Vier-Byte-Pooltag an, das verwendet werden soll, um den zugeordneten Speicher für Suchlisteneinträge zu markieren. Weitere Informationen zu Pooltags finden Sie in der Beschreibung des Tags-Parameters in ExAllocatePoolWithTag.
[in] Depth
Reserviert. Legen Sie diesen Parameter immer auf 0 (null) fest.
Rückgabewert
ExInitializeLookasideListEx gibt STATUS_SUCCESS zurück, wenn der Aufruf erfolgreich ist. Mögliche Rückgabewerte sind der folgende Fehlercode:
Rückgabecode | Beschreibung |
---|---|
STATUS_INVALID_PARAMETER_4 | Der PoolType-Parameterwert ist ungültig. |
STATUS_INVALID_PARAMETER_5 | Der Flags-Parameterwert ist ungültig. |
Hinweise
Ein Treiber muss diese Routine aufrufen, um eine Suchliste zu initialisieren, bevor der Treiber mit der Verwendung der Liste beginnen kann. Eine Lookaside-Liste ist ein Pool von Puffern fester Größe, die der Treiber lokal verwalten kann, um die Anzahl der Aufrufe von Systemzuordnungsroutinen zu reduzieren und dadurch die Leistung zu verbessern. Die Puffer werden als Einträge in der Suchliste gespeichert. Alle Einträge in der Liste haben die gleiche einheitliche Größe, die durch den Size-Parameter angegeben wird.
Nachdem ExInitializeLookasideListEx zurückgegeben wurde, wird die Lookaside-Liste initialisiert, enthält jedoch keine Einträge. Wenn ein Client die ExAllocateFromLookasideListEx-Routine aufruft, um einen Eintrag anzufordern, bestimmt diese Routine, dass die Lookaside-Liste leer ist, und ruft die vom Treiber bereitgestellte LookasideListAllocateEx-Routine auf, um den Speicher für einen neuen Eintrag dynamisch zuzuweisen. Zusätzliche Einträge können als Reaktion auf ähnliche Anforderungen von Clients zugeordnet werden. Später, wenn Clients exFreeToLookasideListEx aufrufen, um diese Einträge freizugeben, fügt diese Routine die Einträge in die Suchliste ein. Wenn die Anzahl der Einträge in der Liste einen grenzwert erreicht, der vom Betriebssystem bestimmt wird, fügt ExFreeToLookasideListEx der Liste keine weiteren Einträge mehr hinzu und übergibt diese Einträge stattdessen an die vom Treiber bereitgestellte LookasideListFreeEx-Routine , die freigegeben werden soll.
Wenn der Treiber die Routinen LookasideListAllocateEx und LookasideListFreeEx nicht liefert, verwenden die Routinen ExAllocateFromLookasideListEx und ExFreeToLookasideListEx stattdessen Standardzuordnungs- und Deallocationroutinen.
Die Bereitstellung von LookasideListAllocateEx - und LookasideListFreeEx-Routinen , die nur ExAllocatePoolWithTag und ExFreePool aufrufen, bietet keinen Vorteil. Der gleiche Effekt kann durch eine bessere Leistung erzielt werden, indem einfach die Parameter Allocate und Free auf NULL festgelegt werden.
Bevor ein Treiber entladen wird, muss er alle erstellten Lookaside-Listen explizit freigeben. Andernfalls handelt es sich um einen schwerwiegenden Programmierfehler. Rufen Sie die ExDeleteLookasideListEx-Routine auf, um eine Lookaside-Liste frei zu geben. Diese Routine gibt den Speicher für alle verbleibenden Einträge in der angegebenen Lookaside-Liste frei und entfernt die Liste dann aus dem systemweiten Satz aktiver Lookaside-Listen.
Das Betriebssystem verfolgt alle derzeit verwendeten Lookaside-Listen nach. Da sowohl die Menge des verfügbaren nicht ausseitigen Arbeitsspeichers als auch die Nachfrage nach Suchlisteneinträgen im Laufe der Zeit variieren, passt das Betriebssystem seine Grenzwerte dynamisch für die maximale Anzahl von Einträgen in jeder nicht ausseitigen Lookaside-Liste an.
In Windows 2000 und höheren Versionen von Windows kann eine Lookaside-Liste, die ausgelagerte oder nicht ausgelagerte Einträge enthält, durch eine PAGED_LOOKASIDE_LIST bzw. NPAGED_LOOKASIDE_LIST-Struktur beschrieben werden.
Weitere Informationen zu Lookaside-Listen finden Sie unter Verwenden von Lookaside-Listen.
Aufrufer von ExInitializeLookasideListEx können unter IRQL <= DISPATCH_LEVEL ausgeführt werden, werden jedoch in der Regel unter IRQL = PASSIVE_LEVEL ausgeführt.
Beispiele
Die vom Treiber bereitgestellten Routinen LookasideListAllocateEx und LookasideListFreeEx empfangen lookaside-Parameter , die auf die LOOKASIDE_LIST_EX Struktur verweisen, die die Lookaside-Liste beschreibt. Die Routinen können diesen Parameter verwenden, um auf private Daten zuzugreifen, die der Treiber der Suchliste zugeordnet hat. Der Treiber kann z. B. eine instance der folgenden Struktur zuordnen, um private Daten für jede suchaside-Liste zu sammeln, die er erstellt:
typedef struct
{
ULONG NumberOfAllocations; // number of entries allocated
ULONG NumberOfFrees; // number of entries freed
LOOKASIDE_LIST_EX LookasideField;
} MY_PRIVATE_DATA;
Der Treiber kann eine Suchliste initialisieren, wie im folgenden Codebeispiel gezeigt:
#define ENTRY_SIZE 256
#define MY_POOL_TAG 'tsLL'
MY_PRIVATE_DATA *MyContext;
NTSTATUS status = STATUS_SUCCESS;
MyContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(MY_PRIVATE_DATA), MY_POOL_TAG);
if (MyContext)
{
MyContext.NumberOfAllocations = 0;
MyContext.NumberOfFrees = 0;
status = ExInitializeLookasideListEx(
&MyContext.LookasideField,
MyLookasideListAllocateEx,
MyLookasideListFreeEx,
NonPagedPool,
0,
ENTRY_SIZE,
MY_POOL_TAG,
0);
}
else
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
Das folgende Codebeispiel zeigt, wie die LookasideListAllocateEx-Routine ihren Lookaside-Parameter verwenden kann, um auf die privaten Daten zuzugreifen, die der Lookaside-Liste zugeordnet sind:
PVOID
MyLookasideListAllocateEx(
__in POOL_TYPE PoolType,
__in SIZE_T NumberOfBytes,
__in ULONG Tag,
__inout PLOOKASIDE_LIST_EX Lookaside)
{
MY_PRIVATE_DATA *MyContext;
PVOID NewEntry;
MyContext = CONTAINING_RECORD(Lookaside, MY_PRIVATE_DATA, LookasideField);
NewEntry = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
if (NewEntry)
{
ULONG NumberOfAllocations = (ULONG) InterlockedIncrement((LONG volatile*)&MyContext->NumberOfAllocations);
}
return NewEntry;
}
Das CONTAINING_RECORD Makro ist in der Ntdef.h-Headerdatei definiert. Die LookAsideListFreeEx-Routine kann auf ähnliche Weise ihren Lookaside-Parameter verwenden, um auf private Daten zuzugreifen.
Nachdem die MyLookasideListAllocateEx-Routine in diesem Beispiel zurückgegeben wurde, fügt ExAllocateFromLookasideListEx den Puffer, auf den die NewEntry-Variable verweist, in die Lookaside-Liste ein. Um diesen Einfügevorgang threadsicher zu machen, synchronisiert ExAllocateFromLookasideListEx den Zugriff auf die Lookaside-Liste mit anderen Listeneinfügungs- und Entfernungsvorgängen, die möglicherweise von anderen Threads ausgeführt werden. Wenn ExFreeFromLookasideListEx einen Puffer aus der Lookaside-Liste entfernt, synchronisiert exFreeFromLookasideListEx den Zugriff auf die Liste.
ExAllocateFromLookasideListEx und ExFreeFromLookasideListEx synchronisieren ihre Aufrufe nicht mit den vom Treiber bereitgestellten Routinen LookasideListAllocateEx und LookasideListFreeEx . Wenn also die Routinen MyLookasideListAllocateEx und MyLookasideListFreeEx in den vorherigen Codebeispielen threadsicher sein müssen, muss der Treiber die erforderliche Synchronisierung bereitstellen.
Die Beispielroutine MyLookasideListAllocateEx synchronisiert den Zugriff auf die Variable MyContext-NumberOfAllocations> mit anderen Threads, die diese Variable erhöhen und verringern können. Um diese Synchronisierung bereitzustellen, ruft MyLookasideListAllocateEx die InterlockedIncrement-Routine auf, um diese Variable atomar zu erhöhen. Ebenso kann die MyLookasideListFreeEx-Routine (nicht dargestellt) die InterlockedDecrement-Routine aufrufen, um diese Variable atomar zu dekrementieren.
Wenn der einzige Zweck der Variablen MyContext-NumberOfAllocations> im vorherigen Codebeispiel jedoch nur darin besteht, Statistiken über Lookaside-Listenzuordnungen zu sammeln, sind atomische Inkremente und Dekremente kaum erforderlich. In diesem Fall sollte die Remote-Möglichkeit eines verpassten Inkrements oder Dekrements kein Problem sein.
Weitere Informationen zur Threadsicherheit für Suchlisten finden Sie unter Verwenden von Lookaside Listen.
Anforderungen
Anforderung | Wert |
---|---|
Unterstützte Mindestversion (Client) | Verfügbar ab Windows Vista. |
Zielplattform | Universell |
Header | wdm.h (einschließlich Wdm.h, Ntddk.h, Ntifs.h) |
Bibliothek | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | <= DISPATCH_LEVEL (siehe Abschnitt Hinweise) |