Usar listas de lookaside

Los controladores que deben asignar búferes de tamaño fijo dinámicamente para realizar operaciones de E/S a petición pueden usar las rutinas de compatibilidad de ExXxxLookasideListEx o ExXxxLookasideList . Después de que este controlador inicialice su lista de aspecto, el sistema operativo contendrá algún número de búferes asignados dinámicamente del tamaño dado en la lista de aspecto del controlador, reservando eficazmente un conjunto de búferes reutilizables de tamaño fijo para el controlador. El formato y el contenido de los búferes de tamaño fijo de un controlador (también conocidos como entradas) en su lista de aspecto están determinados por el controlador.

Por ejemplo, los controladores de clase de almacenamiento que deben configurar bloques de solicitud SCSI (SRB) para los controladores de puerto o miniport SCSI subyacentes usan listas de búsqueda. Este controlador de clase asigna búferes para SRB según sea necesario a partir de su lista de aspecto y libera cada búfer de SRB de vuelta a la lista de búsqueda para que la lista de búsqueda se reutilice cada vez que se devuelve un SRB al controlador de clase en un IRP completado. Dado que un controlador de clase de almacenamiento no puede predeterminar cuántos SRB tiene que usar en cualquier momento porque la demanda de E/S en el controlador aumenta y cae, una lista de aspecto es una manera cómoda y económica de administrar la asignación y desasignación de búferes para srBs de tamaño fijo en dicho controlador.

El sistema operativo mantiene el estado de todas las listas de búsqueda paginadas y no paginadas que se están usando actualmente, realizando un seguimiento dinámico de la demanda de asignaciones y desasignaciones de entradas en todas las listas y el grupo de sistemas disponible para las nuevas entradas. Cuando la demanda de asignaciones es alta, el sistema operativo aumenta el número de entradas que contiene en cada lista de aspecto. Cuando la demanda vuelve a caer, libera entradas de lookaside sobrantes al grupo del sistema.

Las listas de búsqueda son seguras para subprocesos. Una lista de búsqueda tiene sincronización integrada para habilitar varios subprocesos que se ejecutan simultáneamente en un controlador para compartir una lista de aspecto. Estos subprocesos pueden asignar búferes de forma segura desde la lista de búsqueda compartida y liberar estos búferes en la lista sin necesidad de que el controlador sin necesidad de sincronizar explícitamente estas operaciones. Sin embargo, para evitar posibles pérdidas y daños en los datos, un conjunto de subprocesos que comparten una lista de búsqueda debe sincronizar explícitamente la inicialización y eliminación de la lista.

Interfaces de lista de lookaside

A partir de Windows Vista, la estructura de LOOKASIDE_LIST_EX describe una lista de aspecto que puede contener búferes paginados o no paginados. Si un controlador proporciona rutinas de asignación y gratis personalizadas para esta lista de aspecto, estas rutinas reciben un contexto privado como parámetro de entrada. Un controlador puede usar este contexto para recopilar datos privados para la lista de búsqueda. Por ejemplo, el contexto puede usarse para contar el número de entradas de lista que la lista asigna y libera dinámicamente. Para obtener un ejemplo de código que muestre cómo usar un contexto de esta manera, vea ExInitializeLookasideListEx.

Las siguientes rutinas proporcionadas por el sistema admiten listas de búsqueda que se describen mediante una estructura de LOOKASIDE_LIST_EX :

ExAllocateFromLookasideListEx

ExDeleteLookasideListEx

ExFlushLookasideListEx

ExFreeToLookasideListEx

ExInitializeLookasideListEx

A partir de Windows 2000, la estructura de PAGED_LOOKASIDE_LIST describe una lista de aspecto que contiene búferes paginados. Si un controlador proporciona rutinas de asignación y gratis personalizadas para esta lista de aspecto, estas rutinas no reciben un contexto privado como parámetro de entrada. Por este motivo, si el controlador está pensado para ejecutarse solo en Windows Vista y versiones posteriores de Windows, considere la posibilidad de usar la estructura de LOOKASIDE_LIST_EX en lugar de la estructura de PAGED_LOOKASIDE_LIST para las listas de búsqueda. Las siguientes rutinas proporcionadas por el sistema admiten listas de búsqueda que se describen mediante una estructura de PAGED_LOOKASIDE_LIST :

ExAllocateFromPagedLookasideList

ExDeletePagedLookasideList

ExFreeToPagedLookasideList

ExInitializePagedLookasideList

A partir de Windows 2000, la estructura de NPAGED_LOOKASIDE_LIST describe una lista de aspecto que contiene búferes no paginados. Si un controlador proporciona rutinas de asignación y gratis personalizadas para esta lista de aspecto, estas rutinas no reciben un contexto privado como parámetro de entrada. De nuevo, si el controlador está pensado para ejecutarse solo en Windows Vista y versiones posteriores de Windows, considere la posibilidad de usar la estructura de LOOKASIDE_LIST_EX en lugar de la estructura de NPAGED_LOOKASIDE_LIST para las listas de búsqueda. Las siguientes rutinas proporcionadas por el sistema admiten listas de búsqueda descritas por una estructura de NPAGED_LOOKASIDE_LIST :

ExAllocateFromNPagedLookasideList

ExDeleteNPagedLookasideList

ExFreeToNPagedLookasideList

ExInitializeNPagedLookasideList

Guías de implementación

Para implementar una lista de aspecto que use una estructura de LOOKASIDE_LIST_EX , siga estas instrucciones de diseño:

  • Llame a ExInitializeLookasideListEx para configurar una lista de búsqueda. En esta llamada, especifique si las entradas de la lista de búsqueda se van a paginar o no paginar búferes. Use búferes no paginados si el propio controlador o cualquier controlador subyacente al que pasa sus entradas de lista de aspecto puede tener acceso a estas entradas en IRQL >= DISPATCH_LEVEL. Use búferes paginados solo si los accesos a las entradas de la lista de búsqueda del controlador siempre se producen en IRQL <= APC_LEVEL.

  • La estructura LOOKASIDE_LIST_EX de la lista de búsqueda siempre debe residir en la memoria del sistema no paginada, independientemente de si las entradas de la lista se paginan o no.

  • Para mejorar el rendimiento, pase punteros NULL para los parámetros Allocate y Free a ExInitializeLookasideListEx a menos que las rutinas de asignación y desasignación de datos deba hacer más que asignar y liberar memoria para las entradas de lista de búsqueda. Por ejemplo, estas rutinas pueden registrar información sobre el uso del controlador de búferes asignados dinámicamente.

  • Una rutina de asignación proporcionada por el controlador puede pasar los parámetros de entrada (PoolType, Tag y Size) que recibe directamente a la rutina ExAllocatePoolWithTag o ExAllocatePoolWithQuotaTag para asignar un nuevo búfer.

  • Para cada llamada a ExAllocateFromLookasideListEx, realice la llamada recíproca a ExFreeToLookasideListEx tan pronto como sea posible siempre que ya no se use una entrada asignada previamente.

Proporcionar rutinas de asignación y gratis que no hacen nada más que llamar a ExAllocatePoolWithTag y ExFreePool, respectivamente, desperdicia ciclos de procesador. ExAllocateFromLookasideListEx realiza las llamadas necesarias a ExAllocatePoolWithTag y ExFreePool automáticamente cuando un controlador pasa punteros NULLAllocate y Free a ExInitializeLookasideListEx.

Cualquier rutina de asignación proporcionada por el controlador no debe asignar memoria para que una entrada del grupo paginado se mantenga en una lista de búsqueda no paginada o viceversa. También debe asignar entradas de tamaño fijo, ya que cualquier llamada de controlador posterior a ExAllocateFromLookasideListEx devuelve la primera entrada que se mantiene actualmente en la lista de lookaside a menos que la lista esté vacía. Es decir, una llamada a ExAllocateFromLookasideListEx provoca una llamada a la rutina De asignación proporcionada por el controlador solo si la lista de lookaside especificada está vacía actualmente. Por lo tanto, en cada llamada a ExAllocateFromLookasideListEx, la entrada devuelta será exactamente el tamaño que el controlador necesita solo si todas las entradas de la lista de aspecto tienen un tamaño fijo. Una rutina de asignación proporcionada por el controlador tampoco debe cambiar el valor tag que el controlador pasó originalmente a ExInitializeLookasideListEx, ya que los cambios en el valor de la etiqueta de grupo harían que la depuración y el seguimiento del uso de memoria del controlador fuera más difícil.

Las llamadas a ExFreeToLookasideListEx almacenan entradas asignadas previamente en la lista de lookaside a menos que la lista ya esté llena (es decir, la lista contiene el número máximo de entradas determinado por el sistema). Para mejorar el rendimiento, un controlador debe realizar una llamada recíproca a ExFreeToLookasideListEx lo antes posible para cada llamada que realiza a ExAllocateFromLookasideListEx. Cuando un controlador libera las entradas de vuelta a su lista de aspecto rápidamente, la próxima llamada del controlador a ExAllocateFromLookasideListEx es mucho menos probable que incurra en la penalización del rendimiento de asignar memoria dinámicamente para una nueva entrada.

Se aplican instrucciones similares a una lista de aspecto que usa una estructura de PAGED_LOOKASIDE_LIST o NPAGED_LOOKASIDE_LIST .