Uso de búferes de memoria
Los controladores suelen usar búferes de memoria para pasar datos hacia y desde el marco y otros controladores o para almacenar información localmente. En este tema se describen los objetos de memoria del marco, las listas de búsqueda, los MDL y los búferes locales.
Uso de objetos de memoria de marco
El marco de trabajo usa objetos de memoria para describir los búferes de memoria que recibe un controlador de y pasa al marco. Cada objeto de memoria de marco representa un búfer.
Para crear un objeto de memoria, el controlador llama a uno de los métodos de objeto siguientes:
WdfMemoryCreate, que crea un objeto de memoria y asigna un búfer de memoria de un tamaño especificado.
WdfMemoryCreatePreallocated, que crea un objeto de memoria para un búfer asignado previamente.
WdfMemoryCreateFromLookaside, que crea un búfer de memoria a partir de una lista de lookaside.
Para obtener un objeto de memoria que representa los búferes de una solicitud de E/S recibida, el controlador llama a WdfRequestRetrieveInputMemory y WdfRequestRetrieveOutputMemory. Para obtener más información sobre cómo recuperar los búferes de una solicitud de E/S, consulte Acceso a los búferes de datos en controladores de Framework-Based.
Para obtener la dirección y el tamaño del búfer de un objeto de memoria, el controlador llama a WdfMemoryGetBuffer.
Para mover datos dentro o fuera del búfer de un objeto de memoria, el controlador llama a WdfMemoryCopyFromBuffer o WdfMemoryCopyToBuffer. Estos métodos de objeto comprueban los tamaños de origen y destino y evitan errores de saturación del búfer.
Si el controlador crea un objeto de memoria llamando a WdfMemoryCreatePreallocated, posteriormente puede asignar un búfer diferente al objeto de memoria llamando a WdfMemoryAssignBuffer.
Cuando un controlador envía una solicitud de E/S a un destino de E/S, normalmente pasa un búfer de entrada o salida a un método de objeto de destino de E/S de marco. El controlador especifica el búfer pasando una estructura de WDF_MEMORY_DESCRIPTOR que describe el búfer o pasando un identificador de objeto de memoria. (Los métodos de objeto de destino de E/S que envían solicitudes de E/S de forma sincrónica requieren una estructura de WDF_MEMORY_DESCRIPTOR y métodos que envían solicitudes de E/S de forma asincrónica requieren un identificador de objeto de memoria).
Para obtener información sobre cuándo un búfer de memoria es válido, vea Ciclo de vida del búfer de memoria.
Usar listas de lookaside
Si el controlador necesitará muchos búferes de aproximadamente el mismo tamaño, debe asignarlos de una lista de aspecto. El controlador crea una lista de aspecto llamando a WdfLookasideListCreate. Posteriormente, el controlador puede obtener búferes de la lista de lookaside llamando a WdfMemoryCreateFromLookaside.
Cada vez que el controlador llama a WdfMemoryCreateFromLookaside, el marco crea un objeto de memoria, obtiene un búfer de la lista de lookaside y asigna el búfer al objeto . Cuando el controlador ha terminado de usar uno de estos objetos de memoria, llama a WdfObjectDelete, que elimina el objeto de memoria y devuelve el espacio del búfer a la lista de aspecto.
El sistema operativo administra los recursos de memoria asignados a la lista de lookaside. Si el controlador solicita un búfer de la lista lookaside cuando ninguno está disponible, como la primera vez que el controlador llama a WdfMemoryCreateFromLookaside, el sistema asigna un búfer y lo asigna a la lista. Cuando el controlador llama a WdfObjectDelete (y el espacio del búfer se devuelve a la lista de aspecto), el sistema mantiene el búfer sin asignar ahora en la lista hasta que el controlador lo necesite de nuevo. El sistema aumenta el tamaño de la lista según sea necesario; por ejemplo, los controladores que solicitan con más frecuencia los búferes reciben listas de aspecto más grandes. Por otro lado, el sistema podría reducir el número de búferes de la lista si el controlador no los usa todos.
Uso de MDL
Algunos controladores usan listas de descriptores de memoria (MDL) para describir los búferes. Por ejemplo, un controlador para un dispositivo de acceso directo a memoria (DMA) debe pasar una MDL al método WdfDmaTransactionInitialize , si llama a ese método.
Un controlador que usa MDL puede obtener una MDL que represente los búferes de una solicitud de E/S recibida llamando a WdfRequestRetrieveInputWdmMdl y WdfRequestRetrieveOutputWdmMdl.
La mayoría de los controladores basados en marcos no usan MDL.
Asignar búferes locales
Un controlador que requiere espacio de búfer interno local que no pasará al marco no tiene que crear objetos de memoria para representar los búferes. El controlador puede llamar a ExAllocatePoolWithTag para asignar búferes internos. Cuando el controlador haya terminado de usar el búfer, debe llamar a ExFreePoolWithTag.
Sin embargo, los controladores también pueden usar objetos de memoria para búferes locales. Una ventaja de usar búferes de memoria, en lugar de llamar a ExAllocatePoolWithTag, es que el marco elimina automáticamente los objetos de memoria y sus búferes cuando se elimina el objeto primario de cada objeto.
Importante
Los DDIs exAllocatePool descritos en este tema han quedado en desuso en Windows 10, versión 2004 y se han reemplazado por ExAllocatePool2 y ExAllocatePool3. Para obtener más información, consulte Actualización de llamadas exAllocatePool en desuso a ExAllocatePool2 y ExAllocatePool3.
Alinear búferes
El controlador puede usar la función WDF_ALIGN_SIZE_UP o WDF_ALIGN_SIZE_DOWN para calcular un tamaño de búfer alineado con un desplazamiento de alineación especificado. Este cálculo es útil si el controlador debe asignar varios búferes contiguos, si cada búfer debe comenzar en un límite de alineación de direcciones.