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