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

指定此操作的标志。 将此参数设置为零或以下一个或多个 MM_ALLOCATE_XXX 标志位的按位 OR:

上述列表中的最后四项仅在 Windows 7 及更高版本的 Windows 中受支持。

含义
MM_DONT_ZERO_ALLOCATION 0x00000001 不要用零填充分配的页面。 默认情况下,MmAllocatePagesForMdlEx 将其分配的页面归零。 通过跳过此操作,可以改进 MmAllocatePagesForMdlEx 调用的性能。 但是,除非从不向用户模式程序公开分配的页面,或者始终覆盖页面的原始内容,然后再向用户模式程序公开分配的页面,否则不得使用此标志。
MM_ALLOCATE_FROM_LOCAL_NODE_ONLY 0x00000002 仅从理想节点分配页。 此标志仅适用于具有非统一内存访问 (NUMA) 体系结构的多处理器系统。 从 Windows Vista 开始,此标志指示必须从当前线程的理想节点分配所有页面。 不会从其他节点分配页。 在早于 Windows Vista 的 Windows 版本中,此标志指示必须从本地节点分配所有页面;即,从当前处理器所属的节点。 有关 NUMA 多处理器系统的详细信息,请参阅 NUMA 支持
MM_ALLOCATE_FULLY_REQUIRED 0x00000004 需要完全分配。 从 Windows 7 开始,如果 MmAllocatePagesForMdlEx 无法分配所有请求的页面,则此标志要求 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 为非零,但部分分配中的每个连续块都保证为 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 开始,调用方可以通过在 Flags 参数中设置MM_ALLOCATE_PREFER_CONTIGUOUS或MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS标志位来替代此例程的默认行为。

MmAllocatePagesForMdlEx 适用于不需要相应虚拟地址的内核模式驱动程序, (也就是说,它们需要物理页面,不需要物理页面在物理上是连续的) ,而对于内核模式驱动程序,如果设备的物理内存在特定的物理地址范围内分配 (,则可以大幅提高性能, AGP 图形卡) 。

根据请求范围中当前可用的物理内存量, MmAllocatePagesForMdlEx 可能会返回描述比请求的内存少的 MDL。 如果未分配内存,例程也可能返回 NULL 。 调用方应检查实际分配给 MDL 的内存量。

调用方必须使用 MmFreePagesFromMdl 释放由 MmAllocatePagesForMdlEx 创建的 MDL 描述的内存页。 调用 MmFreePagesFromMdl 后,调用方还必须调用 ExFreePool 以释放为 MDL 结构分配的内存。

默认情况下, MmAllocatePagesForMdlEx 会用零填充它分配的页面。 调用方可以指定MM_DONT_ZERO_ALLOCATION标志来替代此默认值并可能提高性能。

如果指定 MM_DONT_ZERO_ALLOCATION 标志, 则 MmAllocatePagesForMdlEx 分配的内存将取消初始化。 如果驱动程序要使内存对用户模式软件可见 (,则内核模式驱动程序必须首先将内存归零,以避免泄露) 潜在的特权内容。 有关此标志的详细信息,请参阅 MM_ALLOCATE_XXX

MmAllocatePagesForMdlEx 在单个调用中可以分配的最大内存量为 (4 GB - PAGE_SIZE) 。 仅当有足够的页面可用时,例程才能满足此数量的分配请求。

MmAllocatePagesForMdlEx 在 IRQL <= APC_LEVEL 运行。 允许 MmAllocatePagesForMdlEx 的调用方位于 DISPATCH_LEVEL。 但是,可以通过在 APC_LEVEL 或更低位置调用 来提高驱动程序性能。

要求

要求
目标平台 通用
标头 wdm.h(包括 Wdm.h、Ntddk.h、Ntifs.h)
Library NtosKrnl.lib
DLL NtosKrnl.exe
IRQL 请参见“备注”部分。
DDI 符合性规则 IrqlMmApcLte (wdm)

另请参阅

ExFreePool

MEMORY_CACHING_TYPE

MmAllocatePagesForMdl

MmFreePagesFromMdl

MmMapLockedPages