Freigeben über


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 LOOKASIDE_LIST_EX Struktur, die initialisiert werden soll. Im Gegenzug beschreibt diese Struktur eine leere Lookaside-Liste. Der Aufrufer muss nicht seitenseitigen Systembereich für diese Struktur verwenden, unabhängig davon, ob die Einträge in der Lookaside-Liste aus dem ausgelagerten oder nicht ausgelagerten 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 zuweist. 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, werden Aufrufe von ExAllocateFromPagedLookasideList automatisch den ausgelagerten oder nicht seitenfreien Speicher (wie durch den PoolType Parameter bestimmt) für die neuen Einträge zuweisen.

[in, optional] Free

Ein Zeiger auf einen vom Aufrufer bereitgestellten LookasideListFreeEx Routine, die einen zuvor zugewiesenen Lookaside-List-Eintrag freigibt. Die ExFreeToPagedLookasideList Routine ruft diese LookasideListFreeEx Routine auf, wenn die Lookaside-Liste voll ist (d. a. die Liste enthält bereits die maximale Anzahl von Einträgen, wie vom Betriebssystem bestimmt). Dieser Parameter ist optional und kann als NULL- angegeben werden, wenn keine benutzerdefinierte Deallocation-Routine 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 Lookaside-Liste 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 einen der folgenden EX_LOOKASIDE_LIST_EX_FLAGS_XXX- Flagbits fest.

Flagbit 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 zu auslösen. Dieses Flag ist für die Verwendung mit einer Zuordnungsroutine wie ExAllocatePoolWithQuotaTagvorgesehen, die Kontingente für die Poolnutzung berechnet.

Diese beiden Flagbits schließen sich gegenseitig aus.

Wenn ZuweisenNULL-ist, legen Sie Flag s 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.

If Flags = EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL, the PoolType parameter value is bitwise ORed with the POOL_RAISE_IF_ALLOCATION_FAILURE flag bit to form the PoolType parameter value that is passed to the LookasideListAllocateEx routine. 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.

If Flags = EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE, the PoolType parameter value is bitwise ORed with the POOL_QUOTA_FAIL_INSTEAD_OF_RAISE flag bit to form the PoolType parameter value that is passed to the LookasideListAllocateEx routine. 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 Byte in der Lookaside-Liste an.

[in] Tag

Gibt das Vier-Byte-Pooltag an, das zum Markieren des zugewiesenen Speichers für Lookaside-Listeneinträge verwendet werden soll. Weitere Informationen zu Pooltags finden Sie in der Beschreibung des parameters Tag in ExAllocatePoolWithTag.

[in] Depth

Reserviert. Legen Sie diesen Parameter immer auf 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.

Bemerkungen

Ein Treiber muss diese Routine aufrufen, um eine Lookaside-Liste zu initialisieren, bevor der Treiber mit der Verwendung der Liste beginnen kann. Eine Lookaside-Liste ist ein Pool von Puffern mit fester Größe, die der Treiber lokal verwalten kann, um die Anzahl der Aufrufe an Systemzuordnungsroutinen zu verringern und damit die Leistung zu verbessern. Die Puffer werden als Einträge in der Lookaside-Liste gespeichert. Alle Einträge in der Liste weisen die gleiche einheitliche Größe auf, die durch den Parameter Size 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 die vom Treiber bereitgestellte LookasideListAllocateEx Routine aufruft, um Speicher für einen neuen Eintrag dynamisch zuzuweisen. Zusätzliche Einträge können als Reaktion auf ähnliche Anforderungen von Clients zugewiesen werden. Wenn Clients die ExFreeToLookasideListEx- aufrufen, um diese Einträge freizugeben, fügt diese Routine die Einträge in die Lookaside-Liste ein. Wenn die Anzahl der Einträge in der Liste einen Grenzwert erreicht, der durch das Betriebssystem bestimmt wird, wird ExFreeToLookasideListEx beendet, der Liste weitere Einträge hinzuzufügen, und übergibt diese Einträge stattdessen an die vom Treiber bereitgestellte LookasideListFreeEx Routine, die freigegeben werden soll.

Wenn der Treiber nicht LookasideListAllocateEx und LookasideListFreeEx-Routinen liefert, verwenden die ExAllocateFromLookasideListEx und ExFreeToLookasideListEx Routinen stattdessen Standardzuordnungs- und Deallocation-Routinen.

Es gibt keinen Vorteil, LookasideListAllocateEx und LookasideListFreeEx Routinen bereitzustellen, die nichts tun, sondern ExAllocatePoolWithTag und ExFreePoolaufrufen. Der gleiche Effekt kann mit einer besseren Leistung erzielt werden, indem sie einfach die Zuordnen und Free Parameter auf NULL-festlegen.

Bevor ein Treiber entladen wird, muss er explizit alle erstellten Lookaside-Listen freigeben. Dies ist ein schwerwiegender Programmierfehler. Rufen Sie die ExDeleteLookasideListEx Routine auf, um eine Lookaside-Liste freizulassen. Diese Routine gibt den Speicher für alle verbleibenden Einträge in der angegebenen Lookaside-Liste frei und entfernt dann die Liste aus der systemweiten Gruppe aktiver Lookaside-Listen.

Das Betriebssystem verfolgt alle Lookaside-Listen, die derzeit verwendet werden. Da sowohl die Menge des verfügbaren nicht seitenseitigen Arbeitsspeichers als auch die Nachfrage nach Nachschlagelisteneinträgen im Laufe der Zeit variieren, passt das Betriebssystem seine Grenzwerte dynamisch für die maximale Anzahl von Einträgen in jeder nicht seitenseitigen Lookaside-Liste an.

In Windows 2000 und höheren Versionen von Windows kann eine Lookaside-Liste mit seitenseitigen oder nicht seitenseitigen Einträgen durch eine PAGED_LOOKASIDE_LIST oder NPAGED_LOOKASIDE_LIST Struktur beschrieben werden.

Weitere Informationen zu Lookaside-Listen finden Sie unter Using Lookaside Lists.

Aufrufer von ExInitializeLookasideListEx- können unter IRQL-<= DISPATCH_LEVEL ausgeführt werden, werden jedoch in der Regel bei IRQL = PASSIVE_LEVEL ausgeführt.

Beispiele

Die vom Treiber bereitgestellten LookasideListAllocateEx und LookasideListFreeEx Routinen empfangen beide 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 Lookaside-Liste zugeordnet hat. Beispielsweise kann der Treiber eine Instanz der folgenden Struktur zuweisen, um private Daten für jede von ihm erstellten Lookaside-Liste zu sammeln:

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 Lookaside-Liste 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;
}

Im folgenden Codebeispiel wird gezeigt, wie die LookasideListAllocateEx-Routine den 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 wird in der Ntdef.h-Headerdatei definiert. Die LookAsideListFreeEx- Routine kann den Lookaside Parameter auch verwenden, um auf private Daten zuzugreifen.

Nachdem die MyLookasideListAllocateEx Routine in diesem Beispiel zurückgegeben wurde, fügt ExAllocateFromLookasideListEx den Puffer ein, auf den die NewEntry Variable in die Lookaside-Liste verweist. Um diesen Einfügevorgang threadsicher zu machen, synchronisiert ExAllocateFromLookasideListEx seinen Zugriff auf die Lookaside-Liste mit anderen Listeneinfügungs- und Entfernungsvorgängen, die von anderen Threads ausgeführt werden können. Wenn ExFreeFromLookasideListEx einen Puffer aus der Lookaside-Liste entfernt, synchronisiert er den Zugriff auf die Liste.

ExAllocateFromLookasideListEx und ExFreeFromLookasideListEx synchronisieren ihre Aufrufe nicht mit der vom Treiber bereitgestellten LookasideListAllocateEx- und LookasideListFreeEx Routinen. Wenn die MyLookasideListAllocateEx und MyLookasideListFreeEx Routinen in den vorherigen Codebeispielen threadsicher sein muss, muss der Treiber die erforderliche Synchronisierung bereitstellen.

Die Beispielroutine MyLookasideListAllocateExsynchronisiert den Zugriff auf die MyContext->NumberOfAllocations-Variable 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 MyContext->NumberOfAllocations Variable im vorherigen Codebeispiel lediglich darin besteht, Statistiken zu Lookaside-Listenzuordnungen zu sammeln, sind atomische Schritten und Dekrementierungen kaum erforderlich. In diesem Fall sollte die Remotemöglichkeit eines verpassten Inkrements oder einer Dekrementierung keine Sorge sein.

Weitere Informationen zur Threadsicherheit für Lookaside-Listen finden Sie unter Using Lookaside Lists.

Anforderungen

Anforderung Wert
mindestens unterstützte Client- Verfügbar ab Windows Vista.
Zielplattform- Universal
Header- wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
Library NtosKrnl.lib
DLL- NtosKrnl.exe
IRQL- <= DISPATCH_LEVEL (siehe Abschnitt "Hinweise")

Siehe auch

ExAllocateFromLookasideListEx

ExAllocatePoolWithQuotaTag

ExAllocatePoolWithTag-

ExDeleteLookasideListEx

ExFreePool-

ExFreeToLookasideListEx

InterlockedDecrement-

InterlockedIncrement-

LOOKASIDE_LIST_EX

LookasideListAllocateEx

LookasideListFreeEx-

NPAGED_LOOKASIDE_LIST

PAGED_LOOKASIDE_LIST

POOL_TYPE