Función ExInitializeLookasideListEx (wdm.h)
La rutina ExInitializeLookasideListEx inicializa una lista de lookaside.
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 búsqueda 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 de búsqueda 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 de LookasideListAllocate Ex proporcionada por el autor de la llamada que asigna una nueva entrada de lookaside-list. La rutina ExAllocateFromLookasideListEx llama a esta rutina LookasideListAllocateEx si la lista de búsqueda 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, llama a ExAllocateFromPagedLookasideList asignar automáticamente el almacenamiento paginado o no paginado (determinado por el parámetro PoolType) para las nuevas entradas.
[in, optional] Free
Puntero a un LookasideListFreeEx proporcionado por el autor de la llamada rutina 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 determine 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 liberar 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 de POOL_TYPE válido.
[in] Flags
Especifica un valor de marca opcional para modificar el comportamiento predeterminado de la rutina de 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 Asignar es null, establezca Marcas 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 de parámetro PoolType es ORed bit a bit con el bit de marca de POOL_RAISE_IF_ALLOCATION_FAILURE para formar el valor de parámetro PoolType que se pasa a la rutina de LookasideListAllocateEx. La rutina LookasideListAllocateEx puede pasar este valor PoolType, sin modificaciones, a la rutina ExAllocatePoolWithTag. Para obtener más información sobre la marca de POOL_RAISE_IF_ALLOCATION_FAILURE, vea ExAllocatePoolWithTag.
Si Flags = EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE, el valor del parámetro PoolType bit a bit es ORed con el bit de marca de POOL_QUOTA_FAIL_INSTEAD_OF_RAISE para formar el valor de parámetro PoolType que se pasa a la rutina de LookasideListAllocateEx. La rutina lookasideListAllocateEx puede pasar este valor PoolType, sin modificaciones, a la rutina de ExAllocatePoolWithQuotaTag. Para obtener más información sobre la marca de POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, vea ExAllocatePoolWithQuotaTag.
[in] Size
Especifica el tamaño, en bytes, de cada entrada de la lista de búsqueda.
[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, vea 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. Los valores devueltos posibles 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 Flags parámetro no es válido. |
Observaciones
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 lo tanto, mejorar el rendimiento. Los búferes se almacenan como entradas en la lista de búsqueda. Todas las entradas de la lista tienen el mismo tamaño uniforme, que especifica el parámetro Size.
Después de devuelve exInitializeLookasideListEx, se inicializa la lista de lookaside, pero no contiene entradas. Cuando un cliente llama a la rutina ExAllocateFromLookasideListEx para solicitar una entrada, esta rutina determina que la lista de búsqueda está vacía y llama a la rutina de 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 al ExFreeToLookasideListEx para liberar estas entradas, esta rutina inserta las entradas en la lista de búsqueda. 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 al controlador proporcionado LookasideListFreeEx rutina que se va a liberar.
Si el controlador no proporciona LookasideListAllocateEx y rutinas de LookasideListFreeEx, las rutinas de ExAllocateFromLookasideListEx y ExFreeToLookasideListEx usan rutinas predeterminadas de asignación y desasignación en su lugar.
No hay ninguna ventaja de proporcionar LookasideListAllocateEx y rutinas de 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 el Asignar y parámetros free en NULL.
Antes de descargar un controlador, debe liberar explícitamente las listas de búsqueda creadas. 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 en la lista de lookaside especificada y, a continuación, quita la lista del conjunto de listas activas de lookaside en todo el sistema.
El sistema operativo realiza un seguimiento de todas las listas de lookaside que están actualmente en uso. Dado que tanto la cantidad de memoria no paginada disponible como 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 búsqueda no paginada.
En Windows 2000 y versiones posteriores de Windows, una lista de búsqueda 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 búsqueda, vea Using Lookaside Lists.
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 reciben parámetros Lookaside que apuntan a la estructura de LOOKASIDE_LIST_EX que describe la lista de lookaside. Las rutinas pueden usar este parámetro para tener acceso 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 crea:
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 de 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 la rutina MyLookasideListAllocateEx de este ejemplo devuelve, 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 búsqueda con otras operaciones de inserción y eliminación de listas que podrían realizar otros subprocesos. Del mismo modo, 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 LookasideListAllocateEx y rutinas de LookasideListFreeEx proporcionadas por el controlador. Por lo tanto, si las rutinas de 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 del MyContext->NumberOfAllocations variable 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 esta variable de forma atómica.
Sin embargo, si el único propósito del MyContext->NumberOfAllocations variable en el ejemplo de código anterior es simplemente recopilar estadísticas sobre asignaciones de listas de búsqueda, incrementos atómicos y decrementos apenas son necesarios. En este caso, la posibilidad remota de un incremento o disminución perdidos no debe ser un problema.
Para obtener más información sobre la seguridad de los subprocesos para las listas de búsqueda, consulte Using Lookaside Lists.
Requisitos
Requisito | Valor |
---|---|
cliente mínimo admitido | Disponible a partir de Windows Vista. |
de la plataforma de destino de | Universal |
encabezado de | wdm.h (include Wdm.h, Ntddk.h, Ntifs.h) |
biblioteca de | NtosKrnl.lib |
DLL de | NtosKrnl.exe |
irQL | <= DISPATCH_LEVEL (consulte la sección Comentarios) |