MmAllocateNodePagesForMdlEx 函数 (wdm.h)

MmAllocateNodePagesForMdlEx 例程从理想的节点分配非分页物理内存,并分配 MDL 结构来描述此内存。

语法

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

参数

[in] LowAddress

第一个地址范围的起始位置的物理地址,分配的页面可以来自该范围。 如果 MmAllocateNodePagesForMdlEx 无法分配第一个地址范围中请求的字节数,则例程会循环访问其他地址范围以获取更多页面。 每次迭代时,mmAllocateNodePagesForMdlExSkipBytes 的值添加到上一个起始地址,以计算下一个地址范围的开始。

[in] HighAddress

分配的页面可以来自的第一个地址范围的末尾的物理地址。

[in] SkipBytes

要从上一地址范围的开头跳过的字节数,分配的页面可以来自该范围。 SkipBytes 必须是虚拟内存页大小的整数倍,以字节为单位。

[in] TotalBytes

要为 MDL 分配的总字节数。

[in] CacheType

一个 MEMORY_CACHING_TYPE 值,该值指示所请求内存允许的缓存类型。

[in] IdealNode

理想的节点数。 如果多处理器系统包含 N 个节点,则有效节点数的范围为 0 到 N-1。 驱动程序可以调用 KeQueryHighestNodeNumber 例程以获取最高的节点数。 单处理器或非 NUMA 多处理器系统只有一个节点(节点 0),从中分配内存。 对于 NUMA 多处理器系统,如果可能,则从理想的节点进行分配。 如果在理想节点中没有足够的内存来满足分配请求,并且调用方未设置MM_ALLOCATE_FROM_LOCAL_NODE_ONLY标志,MmAllocateNodePagesForMdlEx 将尝试从其他节点分配内存。

[in] Flags

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

  • MM_DONT_ZERO_ALLOCATION

  • MM_ALLOCATE_FROM_LOCAL_NODE_ONLY

  • MM_ALLOCATE_FULLY_REQUIRED

  • MM_ALLOCATE_NO_WAIT

  • MM_ALLOCATE_PREFER_CONTIGUOUS

  • MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS

  • MM_ALLOCATE_AND_HOT_REMOVE

有关这些标志的详细信息,请参阅 MM_ALLOCATE_XXX

返回值

MmAllocateNodePagesForMdlEx 返回指向 MDL 结构的指针(如果成功)。 否则,如果例程无法分配任何内存,则例程返回 NULL

NULL 的返回值 指示指定的地址范围中没有可用的物理内存页,或者没有足够的内存池可用于分配 MDL 结构。

如果例程成功分配请求的内存的一些(但不是全部),则 MDL 将描述与例程能够分配的相同物理内存。

言论

在非统一内存访问(NUMA)多处理器系统中,调用方可以指定要从中分配内存的理想节点。 节点是一组处理器,可共享对内存区域的快速访问。 在非 NUMA 多处理器或单处理器系统中,MmAllocateNodePagesForMdlEx 将所有内存视为属于单个节点并从此节点分配内存。

默认情况下,MmAllocateNodePagesForMdlEx 返回的物理内存页不是连续页。 调用方可以通过在 Flags 参数中设置MM_ALLOCATE_PREFER_CONTIGUOUS或MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS标志位来替代此例程的默认行为。

mmAllocateNodePagesForMdlEx 不会将分配的物理内存映射到虚拟内存中。 如有必要,调用方可以调用例程(如 MmMapLockedPagesSpecifyCache)来映射 MDL 描述的物理内存页。

MmAllocateNodePagesForMdlEx 设计用于不需要相应虚拟地址的内核模式驱动程序(也就是说,他们需要物理页,不需要它们是物理连续的),对于内核模式驱动程序,如果设备的物理内存分配在特定物理地址范围(例如, AGP 图形卡)。

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

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

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

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

MmAllocateNodePagesForMdlEx 可以在单个调用中分配的最大内存量为(4 千兆字节 - PAGE_SIZE)。 仅当有足够的页面可用时,该例程才能满足此金额的分配请求。

mmAllocateNodePagesForMdlEx 在 IRQL <= APC_LEVEL 运行。 如有必要,驱动程序可以在DISPATCH_LEVEL调用 MmAllocateNodePagesForMdlEx。 但是,可以通过在APC_LEVEL或以下调用来提高驱动程序性能。

要求

要求 价值
最低支持的客户端 从 Windows 8 开始可用。
目标平台 普遍
标头 wdm.h (包括 Wdm.h、Ntddk.h、Ntifs.h)
NtosKrnl.lib
DLL NtosKrnl.exe
IRQL <= DISPATCH_LEVEL (请参阅“备注”部分)。

另请参阅

ExFreePool

KeQueryHighestNodeNumber

MDL

MEMORY_CACHING_TYPE

MM_ALLOCATE_XXX

mmFreePagesFromMdl

mmMapLockedPagesSpecifyCache