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


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

Подпрограмма MmAllocatePagesForMdlEx выделяет непагированные страницы физической памяти для MDL.

Используйте эту подпрограмму вместо MmAllocatePagesForMdl.

Синтаксис

PMDL MmAllocatePagesForMdlEx(
  [in] PHYSICAL_ADDRESS    LowAddress,
  [in] PHYSICAL_ADDRESS    HighAddress,
  [in] PHYSICAL_ADDRESS    SkipBytes,
  [in] SIZE_T              TotalBytes,
  [in] MEMORY_CACHING_TYPE CacheType,
  [in] ULONG               Flags
);

Параметры

[in] LowAddress

Задает физический адрес начала первого диапазона адресов, из которого могут поступать выделенные страницы. Если MmAllocatePagesForMdlEx не может выделить запрошенное количество байтов в первом диапазоне адресов, он выполняет итерацию по дополнительным диапазонам адресов, чтобы получить больше страниц. При каждой итерации MmAllocatePagesForMdlEx добавляет значение SkipBytes в предыдущий адрес начала, чтобы получить начало следующего диапазона адресов.

[in] HighAddress

Задает физический адрес конца первого диапазона адресов, из который могут поступать выделенные страницы.

[in] SkipBytes

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

[in] TotalBytes

Указывает общее количество байтов, выделяемых для MDL.

[in] CacheType

Указывает значение MEMORY_CACHING_TYPE, указывающее тип кэширования, который разрешен для запрошенной памяти.

[in] Flags

Задает флаги для этой операции. Установите для этого параметра значение нуля или битовое значение OR одного или нескольких из следующих битов флагов MM_ALLOCATE_XXX:

Последние четыре элемента в предыдущем списке поддерживаются только в Windows 7 и более поздних версиях Windows.

Ценность Значение
MM_DONT_ZERO_ALLOCATION 0x00000001 Не заполняйте выделенные страницы нулями. По умолчанию MmAllocatePagesForMdlEx ноль выделенных страниц. Пропуская эту операцию, вы можете повысить производительность вызова MmAllocatePagesForMdlEx. Однако этот флаг не следует использовать, если вы никогда не предоставляете выделенные страницы программам пользовательского режима или всегда перезаписываете исходное содержимое страниц, прежде чем предоставлять выделенные страницы программам пользовательского режима.
MM_ALLOCATE_FROM_LOCAL_NODE_ONLY 0x00000002 Выделите страницы только из идеального узла. Этот флаг применяется только к многопроцессорным системам с неоднородными архитектурами доступа к памяти (NUMA). Начиная с Windows Vista, этот флаг означает, что все страницы должны быть выделены из идеального узла текущего потока. Никакие страницы не должны быть выделены из других узлов. В версиях Windows, предшествующих Windows Vista, этот флаг означает, что все страницы должны быть выделены из локального узла; то есть из узла, к которому принадлежит текущий процессор. Дополнительные сведения о многопроцессорных системах NUMA см. в поддержке NUMA.
MM_ALLOCATE_FULLY_REQUIRED 0x00000004 Требуется полное выделение. Начиная с Windows 7 этот флаг требует, чтобы mmAllocatePagesForMdlEx возвращал ЗНАЧЕНИЕ NULL, если он не может выделить все запрошенные страницы. Подпрограмма возвращает значение, отличное от NULL, только если оно успешно получает все запрошенное выделение. Этот флаг позволяет диспетчеру памяти эффективнее выполнять выделение в случаях, когда вызывающий объект требует полного выделения.
MM_ALLOCATE_NO_WAIT 0x00000008 Не подождите. Начиная с Windows 7, этот флаг указывает, что вызов MmAllocatePagesForMdlEx не должен блокировать вызывающий поток. Как правило, вызывающий объект является драйвером режима ядра, работающим в IRQL < DISPATCH_LEVEL, но не может разрешить его выполнение заблокировано. Например, драйвер может помочь в работе с разбиением по страницам или операциями управления питанием. Независимо от того, задан ли этот флаг, MmAllocatePagesForMdlEx никогда не блокирует вызывающие объекты, работающие в IRQL = DISPATCH_LEVEL.
MM_ALLOCATE_PREFER_CONTIGUOUS 0x00000010 Выделение выполняется таким образом, чтобы свести к минимуму фрагментацию системной памяти. Начиная с Windows 7, этот флаг указывает, что вызывающий объект хочет избежать фрагментирования физической памяти, чтобы сделать более непрерывной память доступной для других вызывающих. Выделенные страницы не гарантированы (и обычно не являются) физически смежными, даже если доступно много непрерывной памяти. Вызывающие пользователи, требующие непрерывной памяти, должны указывать MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS вместо MM_ALLOCATE_PREFER_CONTIGUOUS.
MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS 0x00000020 Требуется непрерывная память. Начиная с Windows 7, этот флаг указывает, что запрошенные страницы должны быть выделены как смежные блоки физической памяти. Если параметр SkipBytes равен нулю, mmAllocatePagesForMdlEx успешно выполняется и возвращает один, непрерывный блок или возвращает значение NULL. Он никогда не возвращает частичное выделение. Для SkipBytes = 0 выделенные страницы удовлетворяют требованиям диапазона адресов, заданным параметрами LowAddress и HighAddress, но страницы не имеют специальных ограничений выравнивания. Если SkipBytes является ненулевой, SkipBytes должен иметь значение 2 и должно быть больше или равно PAGE_SIZE, а значение параметра TotalBytes должно быть несколькими из SkipBytes. В этом случае возвращенный MDL может содержать несколько блоков смежных страниц. То есть каждый блок внутренне связан, но блоки не обязательно связаны друг с другом. Каждый блок смежных страниц гарантированно будет точно пропустить байты и выравнивать по границе SkipBytes. Частичные выделения могут возникать, если SkipBytes ненулевое, но каждый смежный блок в частичном выделении гарантированно имеет длину SkipBytes.
MM_ALLOCATE_FAST_LARGE_PAGES 0x00000040 Начиная с Windows 8, этот флаг указывает, что выделение должно быть удовлетворено из большого кэша страниц операционной системы. Если кэш пуст, выделение завершается ошибкой.  Если MM_ALLOCATE_FAST_LARGE_PAGES не указано, MmAllocatePagesForMdlEx использует кэшированные большие страницы, если они доступны. Если кэш исчерпан, MmAllocatePagesForMdlEx пытается создать дополнительные большие страницы, что может занять много времени. MM_ALLOCATE_FAST_LARGE_PAGES необходимо использовать с флагом MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS. Параметр SkipBytes должен иметь несколько больших размеров страниц.
MM_ALLOCATE_AND_HOT_REMOVE 0x00000100 Начиная с Windows 10, этот флаг приводит к удалению выделенных страниц из пула физической памяти, управляемой Windows. MM_ALLOCATE_AND_HOT_REMOVE нельзя указать вместе с MM_ALLOCATE_FULLY_REQUIRED. Если указана MM_ALLOCATE_AND_HOT_REMOVE, вызывающий объект должен работать в IRQL = PASSIVE_LEVEL.

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

MmAllocatePagesForMdlEx возвращает одно из следующих элементов:

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

Замечания

По умолчанию страницы физической памяти, mmAllocatePagesForMdlEx, не являются смежными страницами. Начиная с Windows 7 вызывающие могут переопределить поведение этой подпрограммы по умолчанию, задав бит флага MM_ALLOCATE_PREFER_CONTIGUOUS или MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS в параметре Flags.

MmAllocatePagesForMdlEx предназначен для драйверов в режиме ядра, которые не нуждаются в соответствующих виртуальных адресах (т. е. они нуждаются в физических страницах и не требуют их физического взаимодействия), а также для драйверов в режиме ядра, которые могут добиться существенного повышения производительности при выделении физической памяти для устройства в определенном физическом диапазоне адресов (например, графическая карта AGP).

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

Вызывающий объект должен использовать MmFreePagesFromMdl, чтобы освободить страницы памяти, описанные MDL, созданной MmAllocatePagesForMdlEx. После вызова MmFreePagesFromMdlвызывающий объект также должен вызвать ExFreePool, чтобы освободить память, выделенную для структуры MDL.

По умолчанию MmAllocatePagesForMdlEx заполняет страницы, выделенные нулями. Вызывающий объект может указать флаг MM_DONT_ZERO_ALLOCATION для переопределения этого по умолчанию и, возможно, повышения производительности.

Память, которая выделяется MmAllocatePagesForMdlEx, неинициализирована, если указать флаг MM_DONT_ZERO_ALLOCATION. Драйвер в режиме ядра должен сначала ноль этой памяти, если драйвер собирается сделать память видимой для программного обеспечения в пользовательском режиме (чтобы избежать утечки потенциально привилегированного содержимого). Дополнительные сведения об этом флаге см. в MM_ALLOCATE_XXX.

Максимальный объем памяти, который MmAllocatePagesForMdlEx может выделяться в одном вызове (4 гигабайта — PAGE_SIZE). Подпрограмма может удовлетворить запрос на выделение этого объема только в том случае, если доступны достаточно страниц.

MmAllocatePagesForMdlEx выполняется в IRQL <= APC_LEVEL. Вызывающие MmAllocatePagesForMdlEx могут находиться в DISPATCH_LEVEL. Однако вы можете повысить производительность драйвера, вызвав APC_LEVEL или ниже.

Требования

Требование Ценность
целевая платформа Всеобщий
заголовка wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
библиотеки NtosKrnl.lib
DLL NtosKrnl.exe
IRQL См. раздел "Примечания".
правил соответствия DDI IrqlMmApcLte(wdm)

См. также

ExFreePool

MEMORY_CACHING_TYPE

MmAllocatePagesForMdl

MmFreePagesFromMdl

MmMapLockedPages