Función ExInitializeLookasideListEx (wdm.h)
La rutina ExInitializeLookasideListEx inicializa una lista de aspecto.
Sintaxis
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
);
Parámetros
[out] Lookaside
Puntero a la estructura LOOKASIDE_LIST_EX que se va a inicializar. A cambio, esta estructura describe una lista de lookaside vacía. El autor de la llamada debe usar espacio del sistema no paginado para esta estructura, independientemente de si las entradas de la lista lookaside se asignan desde la memoria paginada o no paginada. En las plataformas de 64 bits, esta estructura debe estar alineada con 16 bytes.
[in, optional] Allocate
Puntero a una rutina LookasideListAllocateEx proporcionada por el autor de la llamada que asigna una nueva entrada lookaside-list. La rutina ExAllocateFromLookasideListEx llama a esta rutina LookasideListAllocateEx si la lista de lookaside está vacía (no contiene entradas). Este parámetro es opcional y se puede especificar como NULL si no se requiere una rutina de asignación personalizada. Si este parámetro es NULL, las llamadas a ExAllocateFromPagedLookasideList asignan automáticamente el almacenamiento paginado o no paginado (determinado por el parámetro PoolType ) para las nuevas entradas.
[in, optional] Free
Puntero a una rutina LookasideListFreeEx proporcionada por el autor de la llamada que libera una entrada de lookaside-list asignada previamente. La rutina ExFreeToPagedLookasideList llama a esta rutina LookasideListFreeEx si la lista de lookaside está llena (es decir, la lista ya contiene el número máximo de entradas, según lo determinado por el sistema operativo). Este parámetro es opcional y se puede especificar como NULL si no se requiere una rutina de desasignación personalizada. Si este parámetro es NULL, llama a ExFreeToPagedLookasideList libera automáticamente el almacenamiento de las entradas especificadas.
[in] PoolType
Especifica el tipo de grupo de las entradas de la lista lookaside. Establezca este parámetro en un valor de enumeración POOL_TYPE válido.
[in] Flags
Especifica un valor de marca opcional para modificar el comportamiento predeterminado de la rutina LookasideListAllocateEx . Establezca este parámetro en cero o en uno de los siguientes bits de marca EX_LOOKASIDE_LIST_EX_FLAGS_XXX .
Bit de marca | Descripción |
---|---|
EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL | Si se produce un error en la asignación, genere una excepción. |
EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE | Si se produce un error en la asignación, devuelva NULL en lugar de generar una excepción. Esta marca está pensada para su uso con una rutina de asignación, como ExAllocatePoolWithQuotaTag, que cobra cuotas para el uso del grupo. |
Estos dos bits de marca son mutuamente excluyentes.
Si Allocate es NULL, establezca Flags en cero o EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL, pero no en EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE. De lo contrario, el comportamiento de la rutina de asignación predeterminada no está definido.
Si Flags = EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL, el valor del parámetro PoolType es ORed bit a bit con el bit de marca POOL_RAISE_IF_ALLOCATION_FAILURE para formar el valor del parámetro PoolType que se pasa a la rutina LookasideListAllocateEx . La rutina LookasideListAllocateEx puede pasar este valor PoolType , sin modificaciones, a la rutina ExAllocatePoolWithTag . Para obtener más información sobre la marca POOL_RAISE_IF_ALLOCATION_FAILURE, vea ExAllocatePoolWithTag.
Si Flags = EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE, el valor del parámetro PoolType es ORed bit a bit con el bit de marca POOL_QUOTA_FAIL_INSTEAD_OF_RAISE para formar el valor del parámetro PoolType que se pasa a la rutina LookasideListAllocateEx . La rutina LookasideListAllocateEx puede pasar este valor PoolType , sin modificaciones, a la rutina ExAllocatePoolWithQuotaTag . Para obtener más información sobre la marca POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, vea ExAllocatePoolWithQuotaTag.
[in] Size
Especifica el tamaño, en bytes, de cada entrada de la lista de aspecto.
[in] Tag
Especifica la etiqueta de grupo de cuatro bytes que se va a usar para marcar el almacenamiento asignado para las entradas de lookaside-list. Para obtener más información sobre las etiquetas de grupo, consulte la descripción del parámetro Tag en ExAllocatePoolWithTag.
[in] Depth
Reservado. Establezca siempre este parámetro en cero.
Valor devuelto
ExInitializeLookasideListEx devuelve STATUS_SUCCESS si la llamada se realiza correctamente. Entre los posibles valores devueltos se incluyen el siguiente código de error:
Código devuelto | Descripción |
---|---|
STATUS_INVALID_PARAMETER_4 | El valor del parámetro PoolType no es válido. |
STATUS_INVALID_PARAMETER_5 | El valor del parámetro Flags no es válido. |
Comentarios
Un controlador debe llamar a esta rutina para inicializar una lista de aspecto antes de que el controlador pueda empezar a usar la lista. Una lista de aspecto es un grupo de búferes de tamaño fijo que el controlador puede administrar localmente para reducir el número de llamadas a rutinas de asignación del sistema y, por tanto, mejorar el rendimiento. Los búferes se almacenan como entradas en la lista lookaside. Todas las entradas de la lista tienen el mismo tamaño uniforme, especificado por el parámetro Size .
Después de que se devuelva ExInitializeLookasideListEx , la lista de lookaside se inicializa pero no contiene entradas. Cuando un cliente llama a la rutina ExAllocateFromLookasideListEx para solicitar una entrada, esta rutina determina que la lista de lookaside está vacía y llama a la rutina LookasideListAllocateEx proporcionada por el controlador para asignar dinámicamente el almacenamiento para una nueva entrada. Es posible que se asignen entradas adicionales en respuesta a solicitudes similares de los clientes. Más adelante, cuando los clientes llaman a ExFreeToLookasideListEx para liberar estas entradas, esta rutina inserta las entradas en la lista lookaside. Si el número de entradas de la lista alcanza un límite determinado por el sistema operativo, ExFreeToLookasideListEx deja de agregar más entradas a la lista y, en su lugar, pasa estas entradas a la rutina LookasideListFreeEx proporcionada por el controlador para liberarse.
Si el controlador no proporciona rutinas LookasideListAllocateEx y LookasideListFreeEx , las rutinas ExAllocateFromLookasideListEx y ExFreeToLookasideListEx usan rutinas de asignación y desasignación predeterminadas.
No hay ninguna ventaja para proporcionar rutinas LookasideListAllocateEx y LookasideListFreeEx que no hacen nada más que llamar a ExAllocatePoolWithTag y ExFreePool. El mismo efecto se puede lograr con un mejor rendimiento estableciendo simplemente los parámetros Allocate y Free en NULL.
Antes de descargar un controlador, debe liberar explícitamente cualquier lista de lookaside que haya creado. No hacerlo es un error de programación grave. Llame a la rutina ExDeleteLookasideListEx para liberar una lista de lookaside. Esta rutina libera el almacenamiento de las entradas restantes de la lista de lookaside especificada y, a continuación, quita la lista del conjunto de listas de lookaside activas en todo el sistema.
El sistema operativo realiza un seguimiento de todas las listas de lookaside que están actualmente en uso. Dado que la cantidad de memoria no paginada disponible y la demanda de entradas de lista de lookaside varían con el tiempo, el sistema operativo ajusta dinámicamente sus límites para el número máximo de entradas en cada lista de lookaside no paginada.
En Windows 2000 y versiones posteriores de Windows, una lista de aspecto que contiene entradas paginadas o no paginadas se puede describir mediante una estructura de PAGED_LOOKASIDE_LIST o NPAGED_LOOKASIDE_LIST , respectivamente.
Para obtener más información sobre las listas de lookaside, vea Uso de lookaside Listas.
Los autores de llamadas de ExInitializeLookasideListEx se pueden ejecutar en IRQL <= DISPATCH_LEVEL, pero normalmente se ejecutan en IRQL = PASSIVE_LEVEL.
Ejemplos
Las rutinas LookasideListAllocateEx y LookasideListFreeEx proporcionadas por el controlador reciben parámetros lookaside que apuntan a la estructura LOOKASIDE_LIST_EX que describe la lista de lookaside. Las rutinas pueden usar este parámetro para acceder a los datos privados que el controlador ha asociado a la lista de lookaside. Por ejemplo, el controlador podría asignar una instancia de la estructura siguiente para recopilar datos privados para cada lista de lookaside que cree:
typedef struct
{
ULONG NumberOfAllocations; // number of entries allocated
ULONG NumberOfFrees; // number of entries freed
LOOKASIDE_LIST_EX LookasideField;
} MY_PRIVATE_DATA;
El controlador puede inicializar una lista de lookaside, como se muestra en el ejemplo de código siguiente:
#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;
}
En el ejemplo de código siguiente se muestra cómo la rutina LookasideListAllocateEx puede usar su parámetro Lookaside para acceder a los datos privados asociados a la lista 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 se define en el archivo de encabezado Ntdef.h. La rutina LookAsideListFreeEx puede usar de forma similar su parámetro Lookaside para acceder a datos privados.
Después de que se devuelva la rutina MyLookasideListAllocateEx de este ejemplo, ExAllocateFromLookasideListEx inserta el búfer al que apunta la variable NewEntry en la lista de lookaside. Para que esta operación de inserción sea segura para subprocesos, ExAllocateFromLookasideListEx sincroniza su acceso a la lista de lookaside con otras operaciones de inserción y eliminación de listas que otros subprocesos podrían realizar. De forma similar, cuando ExFreeFromLookasideListEx quita un búfer de la lista de lookaside, sincroniza su acceso a la lista.
ExAllocateFromLookasideListEx y ExFreeFromLookasideListEx no sincronizan sus llamadas a las rutinas LookasideListAllocateEx y LookasideListFreeEx proporcionadas por el controlador. Por lo tanto, si las rutinas MyLookasideListAllocateEx y MyLookasideListFreeEx en los ejemplos de código anteriores deben ser seguras para subprocesos, el controlador debe proporcionar la sincronización necesaria.
La rutina de ejemplo, MyLookasideListAllocateEx, sincroniza su acceso a la variable MyContext-NumberOfAllocations> con otros subprocesos que podrían incrementar y disminuir esta variable. Para proporcionar esta sincronización, MyLookasideListAllocateEx llama a la rutina InterlockedIncrement para incrementar de forma atómica esta variable. Del mismo modo, la rutina MyLookasideListFreeEx (no se muestra) puede llamar a la rutina InterlockedDecrement para reducir de forma atómica esta variable.
Sin embargo, si el único propósito de la variable MyContext-NumberOfAllocations> en el ejemplo de código anterior es simplemente recopilar estadísticas sobre las asignaciones de listas de aspecto, los incrementos atómicos y los decrementos apenas son necesarios. En este caso, la posibilidad remota de un incremento o disminución perdidos no debería ser un problema.
Para obtener más información sobre la seguridad de los subprocesos para las listas de lookaside, consulte Uso de lookaside Listas.
Requisitos
Requisito | Value |
---|---|
Cliente mínimo compatible | Disponible a partir de Windows Vista. |
Plataforma de destino | Universal |
Encabezado | wdm.h (incluya Wdm.h, Ntddk.h, Ntifs.h) |
Library | NtosKrnl.lib |
Archivo DLL | NtosKrnl.exe |
IRQL | <= DISPATCH_LEVEL (consulte la sección Comentarios) |