Отправка цепочек структур MDL
В этой статье описывается возможность цепочек MDL в стеке драйверов USB и то, как драйвер клиента может отправлять буфер передачи в виде цепочки структур MDL .
Для большинства USB-контроллеров узлов требуется, чтобы буфер передачи был практически непрерывным. Практически непрерывный означает, что буфер может начинаться и заканчиваться в любом месте страницы, но остальная часть буфера должна начинаться и заканчиваться на границе страницы. Многие драйверы USB-клиента могут удовлетворить это требование. Однако для некоторых клиентских драйверов, особенно для тех, которые должны добавлять или удалять дополнительные данные в буфер или из него, выделение виртуальной непрерывной памяти для буфера передачи не рекомендуется.
Например, рассмотрим сетевой стек из трех драйверов, драйвера сетевого протокола, промежуточного драйвера и драйвера мини-порта. Драйвер протокола инициирует передачу и отправляет пакет следующему драйверу в стеке: промежуточному драйверу. Промежуточный драйвер хочет добавить в пакет пользовательский заголовок (содержащийся в отдельном блоке памяти). Промежуточный драйвер отправляет этот заголовок и полученный пакет следующему драйверу в стеке: драйверу мини-порта. Драйвер мини-порта взаимодействует со стеком драйверов USB и поэтому должен подготовить практически непрерывный буфер передачи. Чтобы создать такой буфер, драйвер мини-порта выделяет большой буфер, добавляет пользовательский заголовок, а затем копирует полезные данные. Так как полезные данные обычно большие, копирование всех полезных данных может оказать значительное влияние на производительность.
Драйвер клиента может преодолеть это влияние на производительность, отправив буфер передачи в виде цепочки списка дескрипторов памяти (MDL). Новый стек драйверов USB в Windows 8, может принимать цепной MDL (см. MDL) от драйвера клиента. Предоставляя цепной MDL, драйвер клиента может ссылаться на несогласованные страницы в памяти вместо выполнения лишних операций копирования. Эта возможность снимает ограничения на количество, размер и выравнивание буферов, позволяя сегментировать буфер передачи в физической памяти.
Для использования цепочек многомерных выражений драйвер клиента должен определить, поддерживает ли базовый стек USB-драйверов, загруженный Windows, возможность, а затем создать цепочку MDL в правильном порядке.
Перед началом работы
Возможность MDL в цепочке поддерживается только для массовой, изохронной передачи и передачи прерываний. Прежде чем запрашивать возможность MDL в цепочке, убедитесь, что драйвер клиента имеет дескриптор USBD для регистрации драйвера в стеке usb-драйверов. Чтобы создать дескриптор USBD, вызовите USBD_CreateHandle. Как правило, драйвер клиента создает дескриптор USBD в своей подпрограмме AddDevice .
Вы можете запросить возможность цепочки MDL в обработчике IRP_MN_START_DEVICE драйвера клиента или в любое время позже. Драйвер клиента не должен запрашивать эту возможность в своей процедуре AddDevice .
Instructions
Вызовите подпрограмму USBD_QueryUsbCapability , чтобы определить, поддерживает ли стек драйверов USB возможность цепочек MDL. Чтобы запросить такую возможность, укажите UsbCapabilityChainedMdls в качестве GUID. Задайте для параметра OutputBuffer значение NULL, а для параметра OutputBufferSize — значение 0.
Проверьте значение NTSTATUS, возвращенное USBD_QueryUsbCapability , и оцените результат. Если подпрограмма завершается успешно, поддерживается возможность цепочек MDL. Любое другое значение указывает, что эта возможность не поддерживается.
Создайте цепочку многомерных выражений. Каждый MDL имеет указатель Next , указывающий на другой MDL.
Драйвер может создать MDL цепочки, вручную задав указатель Далее .
В предыдущем примере драйвер протокола отправляет пакет в виде MDL. Промежуточный драйвер может создать другой MDL,который ссылается на блок памяти с данными заголовка. Чтобы создать цепочку, промежуточный драйвер может указать указатель следующего заголовка MDL на MDL, полученный от драйвера протокола. Затем промежуточный драйвер может перенаправить цепочку двух mdl в драйвер мини-порта, который предоставляет ссылку на цепной MDL в URB для запроса и отправляет запрос в стек драйверов USB. Дополнительные сведения см. в разделе Использование многомерных списков.
При создании URB для запроса ввода-вывода, использующего цепочки многомерных выражений, задайте для элемента TransferBufferMDL связанной структуры URB (например , _URB_BULK_OR_INTERRUPT_TRANSFER или _URB_ISOCH_TRANSFER) первый MDL в цепочке, а для TransferBufferLength задайте общее число передаваемых байтов. Данные могут охватывать несколько записей MDL в цепочке MDL.
В Windows 8 добавлены два новых типа функций URB, которые позволяют драйверу клиента использовать для передачи данных цепочки многомерных выражений. Если вы хотите использовать эту возможность, убедитесь, что для параметра Function заголовка URB задана одна из следующих функций URB:
- URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER_USING_CHAINED_MDL
- URB_FUNCTION_ISOCH_TRANSFER_USING_CHAINED_MDL
Сведения об этих функциях URB см. в разделе _URB_HEADER.
Комментарии
Пример кода, который запрашивает базовый стек драйверов USB, чтобы определить, может ли стек драйверов принимать цепочки многомерных выражений, см. в разделе USBD_QueryUsbCapability.