NdisMAllocateSharedMemory 函数 (ndis.h)

注意

对于 ARM 和 ARM64 处理器,我们强烈建议 NDIS 驱动程序编写器使用 WDF DMA 或 WDM DMA,而不是 NDIS 散点/收集 DMA。

有关 WDF DMA 的详细信息,请参阅 处理 KMDF 驱动程序中的 DMA 操作

有关 WDM DMA 的详细信息,请参阅 管理驱动程序的输入/输出中与 DMA 相关的子主题。

NdisMAllocateSharedMemory 分配和映射主机内存范围,以便同时从主机系统和 DMA NIC 访问内存范围。

语法

void NdisMAllocateSharedMemory(
  [in]  NDIS_HANDLE            MiniportAdapterHandle,
  [in]  ULONG                  Length,
  [in]  BOOLEAN                Cached,
  [out] PVOID                  *VirtualAddress,
  [out] PNDIS_PHYSICAL_ADDRESS PhysicalAddress
);

参数

[in] MiniportAdapterHandle

指定 MiniportInitializeEx 的句柄输入。

[in] Length

指定要分配的字节数。

[in] Cached

(缓存内存始终在 x86 和 x64 系统上使用) ,则忽略此参数。

[out] VirtualAddress

指向调用方提供的变量的指针,此函数在该变量中返回供微型端口驱动程序使用的分配的基虚拟地址。 如果 NdisMAllocateSharedMemory 无法满足其调用方,则返回 NULL 以指示未分配内存。

[out] PhysicalAddress

指向调用方提供的变量的指针,在该变量中,此函数返回一个物理地址(适合由 NIC 使用),该地址对应于 VirtualAddress 中返回的地址,或者返回 NULL

返回值

备注

注意 微型端口驱动程序必须已调用 NdisMRegisterScatterGatherDmaNdisMRegisterDmaChannel ,才能在调用 NdisMAllocateSharedMemory 之前初始化散点/收集 DMA 通道。
 
Microsoft Windows Server 2003、Windows XP Service Pack 1 及更高版本的 Windows 允许总线主 DMA NIC 和从属 DMA NIC 调用 NdisMAllocateSharedMemory。 以前的版本仅允许总线主 DMA NIC 调用 NdisMAllocateSharedMemory。 在这些以前的版本中,如果 MiniportInitializeEx 在调用 NdisMSetMiniportAttributes 时未指定 NIC 是总线主机, 则 NdisMAllocateSharedMemory 仅返回控制权,而不尝试进行分配。

NdisMAllocateSharedMemory 既提供驱动程序用于访问共享内存块的映射虚拟地址范围,也提供 NIC 使用的 NDIS_PHYSICAL_ADDRESS类型范围。 在 PhysicalAddress 中返回的值可由系统进行双重映射。 也就是说, 由 PhysicalAddressLength 中的值描述的“物理”地址范围可以是映射的逻辑地址范围,这些地址范围与每个可能的平台中分配的主机物理地址不匹配。

只能从 MiniportInitializeEx 调用 NdisMAllocateSharedMemory。 请求的分配大小取决于驱动程序编写器(了解 NIC 的功能和特性)如何决定在以下性能与大小两难境地之间进行权衡:

  • 在网络流量较高期间,如果微型端口驱动程序在设备可访问数据缓冲区的共享内存空间不足时运行,则无法保持高 I/O 吞吐量。

    例如,当大量接收传入 NIC 时,微型端口驱动程序可能指示共享内存中的接收缓冲区比从绑定协议驱动程序返回的此类缓冲区要快。 如果未完成的接收缓冲区占用了其所有共享内存空间,则微型端口驱动程序可能必须禁用 NIC 上的接收中断,直到有一些共享内存空间可用于接收缓冲区为止。

  • 另一方面,调用 NdisMAllocateSharedMemory 时选择一个 长度 来预测一些最大传输需求,会使驱动程序的映像更大,其资源使用量也相当不划算,但 I/O 需求的罕见时段除外。 此外,如果系统内存不足, 则 NdisMAllocateSharedMemory 可能不会为驱动程序提供如此大的块,从而迫使驱动程序初始化失败。
提供 的微型端口驱动程序 MiniportSharedMemoryAllocateComplete 函数在解决上述性能与大小两难困境方面具有更大的灵活性。 如果驱动程序具有 MiniportSharedMemoryAllocateComplete 函数,则 MiniportInitializeEx 应仅使用 NdisMAllocateSharedMemory 分配足够的共享内存,以便通过 NIC 进行适度的网络传输操作需求。 此类微型端口驱动程序可以调用 NdisMAllocateSharedMemoryAsyncEx 动态分配更多共享内存,以在 NIC 上传输需求较重的时段分配更多共享内存。 当对传输的高需求消退时,此类驱动程序会调用 NdisMFreeSharedMemory 来释放它分配的额外内存。 请注意,只有总线主 DMA NIC 可以调用 NdisMAllocateSharedMemoryAsyncEx 并导出 MiniportSharedMemoryAllocateComplete。 从属 DMA NIC 不支持此功能。

NdisMAllocateSharedMemoryNdisMAllocateSharedMemoryAsyncEx 是唯一的 NdisXxx 函数,可以调用这些函数来分配驱动程序(使用虚拟地址)和使用相应逻辑地址的 NIC 之间共享的主机内存。

微型端口驱动程序应将它从共享缓存内存中分配的缓冲区对齐在主机数据缓存行边界的一个整数上,以防止在 DMA 期间缓存行撕裂。 缓存行撕裂可能会导致驱动程序中的数据完整性问题,或者要求过度刷新数据缓存来维护数据完整性,或降低驱动程序的 (和系统的) I/O 性能。 MiniportInitializeEx 可以调用 NdisMGetDmaAlignment ,以确定当前平台中驱动程序将在分配的共享内存范围内设置的设备可访问缓冲区的对齐边界。

微型端口驱动程序应设置可分配的共享内存量的限制。 此限制特定于驱动程序,应足够高,以便驱动程序不会耗尽缓冲区。 不要设置过高的限制,因为这可能会浪费共享内存,降低系统性能。

如果驱动程序编写器决定在多处理器计算机中分配更大的共享内存块,并且假设任何 SMP 计算机可能是网络服务器,NIC 的网络传输需求高于工作站,MiniportInitializeEx 也可能在调用 NdisMAllocateSharedMemory 之前调用 NdisSystemProcessorCount

如果对 NdisMAllocateSharedMemory 的 调用失败, MiniportInitializeEx 可以再次调用 请求较小的分配。 但是,如果 MiniportInitializeEx 无法为 NIC 分配足够的共享内存,则必须释放已分配的所有资源并失败初始化。

如果微型端口驱动程序随后指示接收 NdisMIndicateReceiveNetBufferLists,它必须从缓冲池分配一定数量的缓冲区描述符,以映射共享内存块中的 NIC 接收缓冲区。

如果缓存了分配的内存,因此需要在传输时刷新,微型端口驱动程序必须调用 NdisAllocateMdl 来为共享内存范围分配NDIS_BUFFER类型描述符。 微型端口驱动程序必须使用此缓冲区描述符调用 KeFlushIoBuffers 以执行此类刷新。

如果微型端口驱动程序调用 NdisMAllocateSharedMemoryAsyncExNdisMAllocateSharedMemory,当删除 NIC 时,即调用其 MiniportHaltEx 函数时,它必须释放所有未完成的分配,并调用 NdisMFreeSharedMemory

要求

要求
最低受支持的客户端 在 NDIS 6.0 及更高版本中受支持。
目标平台 通用
标头 ndis.h (包括 Ndis.h)
Library Ndis.lib
IRQL PASSIVE_LEVEL

另请参阅

KeFlushIoBuffers

MiniportHaltEx

MiniportInitializeEx

MiniportSharedMemoryAllocateComplete

NdisAllocateMdl

NdisMAllocateNetBufferSGList

NdisMAllocateSharedMemoryAsyncEx

NdisMFreeSharedMemory

NdisMGetDmaAlignment

NdisMIndicateReceiveNetBufferLists

NdisMSetMiniportAttributes

NdisSystemProcessorCount