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 无法分配第一个地址范围中请求的字节数,它将循环访问其他地址范围以获取更多页面。 每次迭代时,mmAllocatePagesForMdlExSkipBytes 的值添加到上一个起始地址,以获取下一个地址范围的开始。

[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 无法分配所有请求的页面,则此标志需要返回 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 必须是两个幂,并且必须大于或等于 PAGE_SIZE,TotalBytes 参数值必须是 SkipBytes 的倍数。 在这种情况下,返回的 MDL 可以包含多个连续页块。 也就是说,每个块在内部是连续的,但块不一定是相互连续的。 每个连续页面块都保证完全是 SkipBytes 长且在 SkipBytes 边界上对齐的。 如果 SkipBytes 为非零,则可以进行部分分配,但部分分配中的每个连续块都保证为 SkipBytes long。
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_FULLY_REQUIRED一起指定MM_ALLOCATE_AND_HOT_REMOVE。 如果指定了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标志位来替代此例程的默认行为。

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 千兆字节 - PAGE_SIZE)。 仅当有足够的页面可用时,该例程才能满足此金额的分配请求。

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

要求

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

另请参阅

ExFreePool

MEMORY_CACHING_TYPE

mmAllocatePagesForMdl

mmFreePagesFromMdl

mmMapLockedPages