Прочитать на английском

Поделиться через


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

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

Использование Объектов Памяти Framework

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

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

  • WdfMemoryCreate, который создает объект памяти и выделяет буфер памяти указанного размера.

  • WdfMemoryCreatePreallocated, которая создает объект памяти для предварительно размещенного буфера.

  • WdfMemoryCreateFromLookaside, который создает буфер памяти из списка lookaside.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Важно!

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

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

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