Funzione ExInitializeLookasideListEx (wdm.h)

La routine ExInitializeLookasideListEx inizializza un elenco lookaside.

Sintassi

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
);

Parametri

[out] Lookaside

Puntatore alla struttura LOOKASIDE_LIST_EX da inizializzare. In caso contrario, questa struttura descrive un elenco lookaside vuoto. Il chiamante deve usare spazio di sistema non di pagina per questa struttura, indipendentemente dal fatto che le voci nell'elenco lookaside vengano allocate dalla memoria paginata o non con pagine. Nelle piattaforme a 64 bit, questa struttura deve essere allineata a 16 byte.

[in, optional] Allocate

Puntatore a una routine LookasideListAllocateEx fornita dal chiamante che alloca una nuova voce lookaside-list. La routine ExAllocateFromLookasideListEx chiama questa routine LookasideListAllocateEx se l'elenco lookaside è vuoto (non contiene voci). Questo parametro è facoltativo e può essere specificato come NULL se non è necessaria una routine di allocazione personalizzata. Se questo parametro è NULL, le chiamate a ExAllocateFromPagedLookasideList allocano automaticamente l'archiviazione paginata o non impaginata (come determinato dal parametro PoolType ) per le nuove voci.

[in, optional] Free

Puntatore a una routine LookasideListFreeEx fornita dal chiamante che libera una voce lookaside-list allocata in precedenza. La routine ExFreeToPagedLookasideList chiama questa routine LookasideListFreeEx se l'elenco lookaside è completo, ovvero l'elenco contiene già il numero massimo di voci, come determinato dal sistema operativo. Questo parametro è facoltativo e può essere specificato come NULL se non è necessaria una routine di deallocazione personalizzata. Se questo parametro è NULL, le chiamate a ExFreeToPagedLookasideList liberano automaticamente l'archiviazione per le voci specificate.

[in] PoolType

Specifica il tipo di pool delle voci nell'elenco lookaside. Impostare questo parametro su un valore di enumerazione valido POOL_TYPE .

[in] Flags

Specifica un valore di flag facoltativo per modificare il comportamento predefinito della routine LookasideListAllocateEx . Impostare questo parametro su zero o su uno dei bit di flag EX_LOOKASIDE_LIST_EX_FLAGS_ XXX seguenti.

Flag bit Descrizione
EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL Se l'allocazione ha esito negativo, generare un'eccezione.
EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE Se l'allocazione ha esito negativo, restituire NULL anziché generare un'eccezione. Questo flag è destinato all'uso con una routine di allocazione, ad esempio ExAllocatePoolWithQuotaTag, che carica quote per l'utilizzo del pool.

Questi due bit di flag si escludono a vicenda.

Se Allocate è NULL, impostare Flag su zero o EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL, ma non su EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE. In caso contrario, il comportamento della routine di allocazione predefinita non è definito.

Se Flags = EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL, il valore del parametro PoolType è bit per bit con il bit di flag POOL_RAISE_IF_ALLOCATION_FAILURE per formare il valore del parametro PoolType passato alla routine LookasideListAllocateEx . La routine LookasideListAllocateEx può passare questo valore PoolType , senza modifiche, alla routine ExAllocatePoolWithTag . Per altre informazioni sul flag di POOL_RAISE_IF_ALLOCATION_FAILURE, vedere ExAllocatePoolWithTag.

Se Flags = EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE, il valore del parametro PoolType è bit per bit con il bit di flag POOL_QUOTA_FAIL_INSTEAD_OF_RAISE per formare il valore del parametro PoolType passato alla routine LookasideListAllocateEx . La routine LookasideListAllocateEx può passare questo valore PoolType , senza modifiche, alla routine ExAllocatePoolWithQuotaTag . Per altre informazioni sul flag di POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, vedere ExAllocatePoolWithQuotaTag.

[in] Size

Specifica le dimensioni, in byte, di ogni voce nell'elenco lookaside.

[in] Tag

Specifica il tag del pool a quattro byte da usare per contrassegnare l'archiviazione allocata per le voci di elenco lookaside. Per altre informazioni sui tag del pool, vedere la descrizione del parametro Tag in ExAllocatePoolWithTag.

[in] Depth

Riservato. Impostare sempre questo parametro su zero.

Valore restituito

ExInitializeLookasideListEx restituisce STATUS_SUCCESS se la chiamata ha esito positivo. I valori restituiti possibili includono il codice di errore seguente:

Codice restituito Descrizione
STATUS_INVALID_PARAMETER_4 Il valore del parametro PoolType non è valido.
STATUS_INVALID_PARAMETER_5 Il valore del parametro Flags non è valido.

Commenti

Un driver deve chiamare questa routine per inizializzare un elenco lookaside prima che il driver possa iniziare a usare l'elenco. Un elenco lookaside è un pool di buffer di dimensioni fisse che il driver può gestire in locale per ridurre il numero di chiamate alle routine di allocazione di sistema e, di conseguenza, per migliorare le prestazioni. I buffer vengono archiviati come voci nell'elenco lookaside. Tutte le voci nell'elenco sono di dimensioni uguali, uniformi, specificate dal parametro Size .

Dopo che ExInitializeLookasideListEx restituisce, l'elenco lookaside viene inizializzato ma non contiene voci. Quando un client chiama la routine ExAllocateFromLookasideListEx per richiedere una voce, questa routine determina che l'elenco lookaside è vuoto e chiama la routine LookasideListAllocateEx fornita dal driver per allocare dinamicamente l'archiviazione per una nuova voce. È possibile allocare voci aggiuntive in risposta a richieste simili dai client. Successivamente, quando i client chiamano ExFreeToLookasideListEx per rilasciare queste voci, questa routine inserisce le voci nell'elenco lookaside. Se il numero di voci nell'elenco raggiunge un limite determinato dal sistema operativo, ExFreeToLookasideListEx smette di aggiungere ulteriori voci all'elenco e passa invece queste voci alla routine LookasideListFreeEx fornita dal driver per essere liberate.

Se il driver non fornisce routine LookasideListAllocateEx e LookasideListFreeEx, le routine ExAllocateFromLookasideListEx e ExFreeToLookasideListEx usano invece routine di allocazione e deallocazione predefinite.

Non vi è alcun vantaggio per fornire routine LookasideListAllocateEx e LookasideListFreeEx che non fanno nulla, ma chiama ExAllocatePoolWithTag e ExFreePool. Lo stesso effetto può essere ottenuto con prestazioni migliori impostando semplicemente i parametri Allocate and Free su NULL.

Prima di scaricare un driver, è necessario liberare esplicitamente qualsiasi elenco lookaside creato. La mancata operazione è un errore di programmazione grave. Chiamare la routine ExDeleteLookasideListEx per liberare un elenco lookaside. Questa routine libera l'archiviazione per le voci rimanenti nell'elenco lookaside specificato e quindi rimuove l'elenco dal set di elenchi lookaside attivi a livello di sistema.

Il sistema operativo tiene traccia di tutti gli elenchi lookaside attualmente in uso. Poiché sia la quantità di memoria non a pagina disponibile sia la domanda di voci di elenco lookaside variano nel tempo, il sistema operativo regola in modo dinamico i relativi limiti per il numero massimo di voci in ogni elenco lookaside non a pagina.

In Windows 2000 e versioni successive di Windows, un elenco lookaside che contiene voci di pagina o non paginate può essere descritto rispettivamente da una struttura PAGED_LOOKASIDE_LIST o NPAGED_LOOKASIDE_LIST .

Per altre informazioni sugli elenchi lookaside, vedere Uso di Lookaside Elenchi.

I chiamanti di ExInitializeLookasideListEx possono essere eseguiti in IRQL = DISPATCH_LEVEL, ma in genere vengono eseguiti in IRQL <= PASSIVE_LEVEL.

Esempio

Le routine LookasideListAllocateEx e LookasideListFreeEx fornite dal driver ricevono entrambi parametri Lookaside che puntano alla struttura LOOKASIDE_LIST_EX che descrive l'elenco lookaside. Le routine possono usare questo parametro per accedere ai dati privati associati all'elenco lookaside. Ad esempio, il driver potrebbe allocare un'istanza della struttura seguente per raccogliere dati privati per ogni elenco lookaside creato:

typedef struct
{
  ULONG NumberOfAllocations;  // number of entries allocated
  ULONG NumberOfFrees;        // number of entries freed
  LOOKASIDE_LIST_EX LookasideField;
} MY_PRIVATE_DATA;

Il driver può inizializzare un elenco lookaside, come illustrato nell'esempio di codice seguente:

#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;
}

Nell'esempio di codice seguente viene illustrato come la routine LookasideListAllocateEx può usare il parametro Lookaside per accedere ai dati privati associati all'elenco lookaside:

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

La macro CONTAINING_RECORD è definita nel file di intestazione Ntdef.h. La routine LookAsideListFreeEx può usare in modo analogo il parametro Lookaside per accedere ai dati privati.

Dopo che la routine MyLookasideListAllocateEx in questo esempio restituisce, ExAllocateFromLookasideListEx inserisce il buffer puntato dalla variabile NewEntry nell'elenco lookaside. Per rendere questa operazione di inserimento thread-safe, ExAllocateFromLookasideListEx sincronizza l'accesso dell'elenco lookaside con altre operazioni di inserimento e rimozione dell'elenco che potrebbero essere eseguite da altri thread. Analogamente, quando ExFreeFromLookasideListEx rimuove un buffer dall'elenco lookaside, sincronizza l'accesso all'elenco.

ExAllocateFromLookasideListEx e ExFreeFromLookasideListEx non sincronizzare le chiamate a LookasideListAllocateEx e LookasideListFreeEx . Pertanto, se le routine MyLookasideListAllocateEx e MyLookasideListFreeEx negli esempi di codice precedenti devono essere thread-safe, il driver deve fornire la sincronizzazione necessaria.

La routine di esempio MyLookasideListAllocateEx sincronizza l'accesso della variabile MyContext-NumberOfAllocations> con altri thread che potrebbero aumentare e decrerere questa variabile. Per fornire questa sincronizzazione, MyLookasideListAllocateEx chiama la routine InterlockedIncrement per aumentare atomicamente questa variabile. Analogamente, la routine MyLookasideListFreeEx (non visualizzata) può chiamare la routine InterlockedDecrement per decrementare atomicamente questa variabile.

Tuttavia, se l'unico scopo della variabile MyContext-NumberOfAllocations> nell'esempio di codice precedente è semplicemente raccogliere statistiche sulle allocazioni di elenchi lookaside, gli incrementi atomici e le decrementi non sono necessari. In questo caso, la possibilità remota di un incremento o decremento non deve essere una preoccupazione.

Per altre informazioni sulla sicurezza dei thread per gli elenchi lookaside, vedere Uso di Lookaside Elenchi.

Requisiti

Requisito Valore
Client minimo supportato Disponibile a partire da Windows Vista.
Piattaforma di destinazione Universale
Intestazione wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
Libreria NtosKrnl.lib
DLL NtosKrnl.exe
IRQL <= DISPATCH_LEVEL (vedere la sezione Osservazioni)

Vedi anche

ExAllocateFromLookasideListEx

ExAllocatePoolWithQuotaTag

ExAllocatePoolWithTag

ExDeleteLookasideListEx

ExFreePool

ExFreeToLookasideListEx

InterlockedDecrement

InterlockedIncrement

LOOKASIDE_LIST_EX

LookasideListAllocateEx

LookasideListFreeEx

NPAGED_LOOKASIDE_LIST

PAGED_LOOKASIDE_LIST

POOL_TYPE