MmAllocateContiguousNodeMemory 函数 (wdm.h)

MmAllocateContiguousNodeMemory 例程分配一系列连续的非分页物理内存,并将其映射到系统地址空间。

语法

PVOID MmAllocateContiguousNodeMemory(
  [in]           SIZE_T           NumberOfBytes,
  [in]           PHYSICAL_ADDRESS LowestAcceptableAddress,
  [in]           PHYSICAL_ADDRESS HighestAcceptableAddress,
  [in, optional] PHYSICAL_ADDRESS BoundaryAddressMultiple,
  [in]           ULONG            Protect,
  [in]           NODE_REQUIREMENT PreferredNode
);

参数

[in] NumberOfBytes

要分配的连续内存块的大小(以字节为单位)。 有关详细信息,请参阅“备注”。

[in] LowestAcceptableAddress

调用方可以使用的最低有效物理地址。 例如,如果设备只能处理处理器物理内存地址范围前 8 MB 以上的位置,则此设备的驱动程序应将 LowestAcceptableAddress 设置为0x0000000000800000。

[in] HighestAcceptableAddress

调用方可以使用的最高有效物理地址。 例如,如果设备只能处理处理器物理内存地址范围前 16 兆字节的位置,则此设备的驱动程序应将 HighestAcceptableAddress 设置为0x0000000000FFFFFF。

[in, optional] BoundaryAddressMultiple

分配的缓冲区不能交叉的物理地址倍数。 物理地址倍数必须始终为 2 的幂。 此参数是可选的,可以指定为零,以指示设备没有特殊的内存边界限制。 有关详细信息,请参阅“备注”。

[in] Protect

指定用于分配内存的保护的标志位。 调用方必须在 Protect 参数中设置以下标志位的一个(但不能同时设置这两个标志位)。

标志位 意义
PAGE_READWRITE 分配读/写、无执行 (NX) 内存。 大多数调用方应设置此标志位。 有关详细信息,请参阅“备注”。
PAGE_EXECUTE_READWRITE 分配可执行的读/写内存。 仅当调用方需要能够在分配的内存中执行指令时,才应设置此标志位。

此外,调用方可以在 Protect 参数中设置以下可选标志位的一个(但不能同时设置这两个)。

标志位 意义
PAGE_NOCACHE 分配非缓存内存。 此标志位实际上类似于调用 MmAllocateContiguousMemorySpecifyCacheCacheType 设置为 MmNonCached
PAGE_WRITECOMBINE 分配写入组合内存。 此标志位实际上类似于调用 MmAllocateContiguousMemorySpecifyCacheCacheType 设置为 mmWriteCombined

如果未指定PAGE_NOCACHE和PAGE_WRITECOMBINE,则分配的内存将完全缓存。 在这种情况下,效果类似于调用 MmAllocateContiguousMemorySpecifyCacheCacheType 设置为 mmCached

[in] PreferredNode

首选节点编号。 如果多处理器系统包含 N 个节点,则节点数从 0 到 N-1。 如果调用方 PreferredNode 设置为MM_ANY_NODE_OK,则例程将选择要从中分配内存的节点。 否则,如果无法从首选节点分配指定地址范围内的内存,则例程返回 NULL

返回值

mmAllocateContiguousNodeMemory 返回已分配内存的基虚拟地址。 如果无法满足请求,则例程返回 NULL

言论

内核模式设备驱动程序调用此例程来分配连续的物理内存块。 调用驱动程序可以指定是否对分配使用无执行 (NX) 内存。 在非统一内存访问(NUMA)多处理器系统中,调用方可以指定要从中分配内存的首选节点。 节点是一组处理器,可共享对内存区域的快速访问。 在非 NUMA 多处理器或单处理器系统中,MmAllocateContiguousNodeMemory 将所有内存视为属于单个节点并从此节点分配内存。

mmAllocateContiguousNodeMemory 分配物理地址空间中连续的非分页内存块。 例程将此块映射到系统地址空间中的连续虚拟内存块,并返回此块基的虚拟地址。 例程将连续内存分配的起始地址与内存页边界对齐。

驱动程序不能访问超出所请求分配大小的内存。 例如,开发人员不应假定其驱动程序可以在请求分配的末尾和下一页边界之间安全地使用内存。

由于连续的物理内存通常供不应求,因此应谨慎使用,并且仅在必要时使用。 在使用连续内存的驱动程序应在驱动程序初始化期间分配此内存,因为随着作系统分配和释放内存,物理内存可能会随着时间而碎片化。 通常,驱动程序从其 DriverEntry 例程调用 MmAllocateContiguousNodeMemory,以分配内部缓冲区供长期使用,并在卸载驱动程序之前释放缓冲区。

不再需要内存时,必须释放由 MmAllocateContiguousNodeMemory 分配的内存。 调用 MmFreeContiguousMemory 例程以释放由 MmAllocateContiguousNodeMemory分配的内存。

mmAllocateContiguousNodeMemory 类似于 MmAllocateContiguousMemorySpecifyCacheNode 例程。 与 mmAllocateContiguousMemorySpecifyCacheNode不同,MmAllocateContiguousNodeMemory 可用于分配无执行内存(NX) 内存。 最佳做法是,除非驱动程序显式要求能够在分配的内存中执行指令,否则驱动程序应分配 NX 内存。 通过分配 NX 内存,驱动程序通过防止恶意软件在此内存中执行指令来提高安全性。 MmAllocateContiguousMemoryMmAllocateContiguousMemorySpecifyCache分配的内存,mmAllocateContiguousMemorySpecifyCacheNode 例程始终可执行。

如果为 BoundaryAddressMultiple 参数指定非零值,则分配的内存块的物理地址范围不会超过此值的整数倍数的地址边界。 除非需要非零值才能解决硬件限制,否则驱动程序应将此参数设置为零。 例如,如果设备无法跨 16 兆字节的物理边界传输数据,驱动程序应为此参数指定0x1000000值,以确保设备看到的地址不会环绕在 16 兆字节边界处。

mmAllocateContiguousNodeMemory 分配的内存未初始化。 如果内核模式驱动程序要使用户模式软件可见(以避免泄露潜在特权内容),内核模式驱动程序必须首先为此内存零。

要求

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

另请参阅

DriverEntry

mmAllocateContiguousMemory

mmAllocateContiguousMemorySpecifyCache

mmAllocateContiguousMemorySpecifyCacheNode

mmFreeContiguousMemory