Использование буферов памяти

Драйверы обычно используют буферы памяти для передачи данных в платформу и другие драйверы, а также для локального хранения данных. В этом разделе описываются объекты памяти платформы, списки lookaside, многомерные библиотеки и локальные буферы.

Использование объектов памяти платформы

Платформа использует объекты памяти для описания буферов памяти, которые драйвер получает из платформы и передает в нее. Каждый объект памяти платформы представляет один буфер.

Чтобы создать объект памяти, драйвер вызывает один из следующих методов объекта:

Чтобы получить объект памяти, представляющий буферы полученного запроса ввода-вывода, драйвер вызывает WdfRequestRetrieveInputMemory и WdfRequestRetrieveOutputMemory. Дополнительные сведения о получении буферов запроса ввода-вывода см. в статье Доступ к буферам данных в драйверах Framework-Based.

Чтобы получить адрес и размер буфера объекта памяти, драйвер вызывает WdfMemoryGetBuffer.

Чтобы переместить данные в буфер объекта памяти или из него, драйвер вызывает WdfMemoryCopyFromBuffer или WdfMemoryCopyToBuffer. Эти методы объектов проверяют исходный и целевой размеры и предотвращают ошибки переполнения буфера.

Если драйвер создает объект памяти путем вызова WdfMemoryCreatePreallocated, он может впоследствии назначить другой буфер объекту памяти, вызвав WdfMemoryAssignBuffer.

Когда драйвер отправляет запрос ввода-вывода целевому объекту ввода-вывода, он обычно передает входной или выходной буфер целевому объектному методу платформы ввода-вывода. Драйвер задает буфер путем передачи WDF_MEMORY_DESCRIPTOR структуры, описывающей буфер, или путем передачи дескриптора объекта памяти. (Методы целевых объектов ввода-вывода, которые синхронно отправляют запросы ввода-вывода, требуют WDF_MEMORY_DESCRIPTOR структуры, а методы, которые отправляют запросы ввода-вывода асинхронно, требуют дескриптора объекта памяти.)

Сведения о допустимости буфера памяти см. в разделе Жизненный цикл буфера памяти.

Использование списков lookaside

Если драйверу потребуется несколько буферов примерно одинакового размера, он должен выделить их из списка просмотра. Драйвер создает список lookaside путем вызова WdfLookasideListCreate. Затем драйвер может получить буферы из списка lookaside, вызвав WdfMemoryCreateFromLookaside.

Каждый раз, когда драйвер вызывает WdfMemoryCreateFromLookaside, платформа создает объект памяти, получает буфер из списка lookaside и назначает буфер объекту . Когда драйвер завершает использование одного из этих объектов памяти, он вызывает WdfObjectDelete, который удаляет объект памяти и возвращает буферное пространство в список lookaside.

Операционная система управляет ресурсами памяти, назначенными списку lookaside. Если драйвер запрашивает буфер из списка lookaside, когда нет доступных, например при первом вызове WdfMemoryCreateFromLookaside, система выделяет буфер и назначает его списку. Когда драйвер вызывает WdfObjectDelete (и буферное пространство возвращается в список lookaside), система сохраняет теперь неназначенные буферы в списке до тех пор, пока драйвер не потребует его снова. При необходимости система увеличивает размер списка; Например, драйверы, которые чаще запрашивают буферы, получают более крупные списки lookaside. С другой стороны, система может уменьшить количество буферов в списке, если драйвер использует их не все.

Использование mdls

Некоторые драйверы используют списки дескрипторов памяти (MDL) для описания буферов. Например, драйвер для устройства с прямым доступом к памяти (DMA) должен передать MDL методу WdfDmaTransactionInitialize , если он вызывает этот метод.

Драйвер, использующий mdls, может получить MDL, представляющий буферы полученного запроса ввода-вывода, путем вызова WdfRequestRetrieveInputWdmMdl и WdfRequestRetrieveOutputWdmMdl.

Большинство драйверов на основе платформы не используют многомерные библиотеки.

Выделение локальных буферов

Драйверу, которому требуется локальное внутреннее буферное пространство, которое не будет передаваться в платформу, не нужно создавать объекты памяти для представления буферов. Драйвер может вызывать ExAllocatePoolWithTag для выделения внутренних буферов. После завершения работы с буфером драйвер должен вызвать ExFreePoolWithTag.

Однако драйверы также могут использовать объекты памяти для локальных буферов. Преимущество использования буферов памяти вместо вызова ExAllocatePoolWithTag заключается в том, что платформа автоматически удаляет объекты памяти и их буферы при удалении родительского объекта каждого объекта.

Важно!

DIS ExAllocatePool, обсуждаемые в этом разделе, устарели в Windows 10 версии 2004 и заменены ExAllocatePool2 и ExAllocatePool3. Дополнительные сведения см. в статье Обновление устаревших вызовов ExAllocatePool для ExAllocatePool2 и ExAllocatePool3.

Выравнивание буферов

Драйвер может использовать функцию WDF_ALIGN_SIZE_UP или WDF_ALIGN_SIZE_DOWN для вычисления размера буфера, выровненного по указанному смещению выравнивания. Это вычисление полезно, если драйвер должен выделить несколько смежных буферов, если каждый буфер должен начинаться с границы выравнивания адресов.