Функция MmGetSystemAddressForMdlSafe (wdm.h)

Макрос MmGetSystemAddressForMdlSafe возвращает неупакованный виртуальный адрес системного пространства для буфера, описываемого указанным MDL.

Синтаксис

PVOID MmGetSystemAddressForMdlSafe(
  [in] PMDL  Mdl,
  [in] ULONG Priority
);

Параметры

[in] Mdl

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

[in] Priority

Задает значение MM_PAGE_PRIORITY , указывающее важность успешного выполнения в условиях низкой доступности PTE. Укажите значение приоритета LowPagePriority, NormalPagePriority или HighPagePriority. Начиная с Windows 8, указанное значение приоритета может быть побитовое oRed с флагами MdlMappingNoWrite или MdlMappingNoExecute.

  • LowPagePriority указывает, что запрос на сопоставление может завершиться ошибкой, если в системе довольно мало ресурсов. Примером такой ситуации является некритичное сетевое подключение, в котором драйвер может обработать сбой сопоставления.

  • NormalPagePriority указывает, что запрос на сопоставление может завершиться ошибкой, если в системе очень мало ресурсов. Примером такой ситуации является некритический запрос локальной файловой системы.

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

  • MdlMappingNoWrite указывает, что сопоставленные физические страницы должны быть настроены как память без записи (только для чтения). Начиная с Windows 8, этот бит флага может быть побитовым с параметром MM_PAGE_PRIORITY, чтобы указать память, в которой отключены операции записи.

  • MdlMappingNoExecute указывает, что сопоставленные физические страницы должны быть настроены как память без выполнения. Начиная с Windows 8, этот бит флага может быть побитовым с параметром MM_PAGE_PRIORITY, чтобы указать память, в которой отключено выполнение инструкций. Рекомендуется, чтобы драйверы, написанные для Windows 8 и более поздних версий Windows, всегда должны указывать память без выполнения, если только исполняемая память не требуется явным образом.

Возвращаемое значение

MmGetSystemAddressForMdlSafe возвращает виртуальный адрес базового системного пространства, который сопоставляет физические страницы, описываемые указанным MDL. Если страницы еще не сопоставлены с системным адресным пространством и попытка сопоставить их завершается сбоем, возвращается значение NULL .

Комментарии

Эта подпрограмма сопоставляет физические страницы, описанные указанным MDL, в системное адресное пространство, если они еще не сопоставлены с системным адресным пространством.

Драйверы запрограммированных устройств ввода-вывода (PIO) вызывают эту подпрограмму для сопоставления буфера пользовательского режима, который описан в MDL в Irp-MdlAddress> и который уже сопоставлен с диапазоном виртуальных адресов в пользовательском режиме, с диапазоном в системном адресном пространстве.

При входе в эту подпрограмму указанный MDL должен описывать физические страницы, которые заблокированы. Заблокированный MDL можно создать с помощью процедуры MmProbeAndLockPages, MmBuildMdlForNonPagedPool, IoBuildPartialMdl или MmAllocatePagesForMdlEx .

Если сопоставление системных адресов и пространств, возвращаемое MmGetSystemAddressForMdlSafe , больше не требуется, оно должно быть освобождено. Действия, необходимые для освобождения сопоставления, зависят от того, как был создан MDL. Вот четыре возможных варианта:

  • Если MDL был создан путем вызова подпрограммы MmProbeAndLockPages , явно освобождать сопоставление системных адресов и пространств не требуется. Вместо этого вызов подпрограммы MmUnlockPages освобождает сопоставление, если оно было выделено.

  • Если MDL был создан путем вызова подпрограммы MmBuildMdlForNonPagedPool , MmGetSystemAddressForMdlSafe повторно использует существующее сопоставление системного адресного пространства вместо создания нового. В этом случае очистка не требуется (то есть разблокировка и отмена сопоставления не требуются).

  • Если MDL был создан путем вызова подпрограммы IoBuildPartialMdl , драйвер должен вызвать подпрограмму MmPrepareMdlForReuse или процедуру IoFreeMdl , чтобы освободить сопоставление системного адресного пространства.

  • Если MDL был создан путем вызова процедуры MmAllocatePagesForMdlEx , драйвер должен вызвать подпрограмму MmUnmapLockedPages , чтобы освободить сопоставление системных адресов и пространства. Если mmGetSystemAddressForMdlSafe вызывается несколько раз для MDL, последующие вызовы MmGetSystemAddressForMdlSafe просто возвращают сопоставление, созданное при первом вызове. Для освобождения этого сопоставления достаточно одного вызова MmUnmapLockedPages .

Начиная с Windows 7 и Windows Server 2008 R2, нет необходимости явно вызывать MmUnmapLockedPages для MDL, созданного MmAllocatePagesForMdlEx. Вместо этого вызов подпрограммы MmFreePagesFromMdl освобождает сопоставление системного адресного пространства, если оно было выделено.

Чтобы создать сопоставление системных адресов и пространств, MmGetSystemAddressForMdlSafe вызывает MmMapLockedPagesSpecifyCache с параметром CacheType , равным MmCached. Драйвер, которому требуется тип кэша, отличный от MmCached , должен вызывать MmMapLockedPagesSpecifyCache напрямую, а не mmGetSystemAddressForMdlSafe. Дополнительные сведения о параметре CacheType см. в разделе MmMapLockedPagesSpecifyCache.

При вызове MmMapLockedPagesSpecifyCache указанный тип кэша используется только в том случае, если страницы, описанные в MDL, еще не имеют связанного типа кэша. Однако почти во всех случаях страницы уже имеют связанный тип кэша, и этот тип кэша используется в новом сопоставлении. Исключением из этого правила являются страницы, выделенные mmAllocatePagesForMdl, которая задает тип кэша MmCached независимо от исходного типа кэша страниц.

Только один поток за раз может безопасно вызывать MmGetSystemAddressForMdlSafe для конкретного MDL, так как эта подпрограмма предполагает, что вызывающий поток владеет MDL. Тем не менее MmGetSystemAddressForMdlSafe можно вызывать несколько раз для одного MDL путем выполнения всех вызовов из одного потока или, если вызовы выполняются из нескольких потоков, путем явной синхронизации вызовов.

Если драйвер должен разделить запрос на более мелкие запросы, драйвер может выделить дополнительные многомерные списки или драйвер может использовать подпрограмму IoBuildPartialMdl .

Возвращаемый базовый адрес имеет то же смещение, что и виртуальный адрес в MDL.

Windows 98 не поддерживает MmGetSystemAddressForMdlSafe. Вместо этого используйте MmGetSystemAddressForMdl .

Так как этот макрос вызывает MmMapLockedPagesSpecifyCache, для его использования может потребоваться связывание с NtosKrnl.lib.

Требования

Требование Значение
Минимальная версия клиента Windows 2000
Верхняя часть wdm.h
IRQL <= DISPATCH_LEVEL
Правила соответствия DDI MdlAfterReqCompletedIntIoctlA(kmdf), MdlAfterReqCompletedIoctlA(kmdf), MdlAfterReqCompletedReadA(kmdf), MdlAfterReqCompletedWriteA(kmdf)