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 来初始化散点/收集 DMA 通道,然后再调用 NdisMAllocateSharedMemory
 
Microsoft Windows Server 2003、Windows XP Service Pack 1 和更高版本的 Windows 允许总线主 DMA NIC 和从属 DMA NIC 调用 NdisMAllocateSharedMemory。 以前的版本仅允许总线主 DMA NIC 调用 NdisMAllocateSharedMemory。 在这些以前的版本中,如果 MiniportInitializeEx 未指定 NIC 是总线主控形状,则它调用 NdisMSetMiniportAttributes时,NdisMAllocateSharedMemory 只是返回控件而不尝试进行分配。

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

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

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

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

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

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

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

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

MiniportInitializeEx 还可以在调用 NdisMAllocateSharedMemory 之前调用 NdisSystemProcessorCount,前提是驱动程序编写器决定在多处理器计算机上分配更大的共享内存块,前提是任何 SMP 计算机可能是 NIC 上具有高于工作站的网络传输需求的网络服务器。

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

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

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

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

要求

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

另请参阅

KeFlushIoBuffers

MiniportHaltEx

MiniportInitializeEx

MiniportSharedMemoryAllocateComplete

NdisAllocateMdl

NdisMAllocateNetBufferSGList

NdisMAllocateSharedMemoryAsyncEx

NdisMFreeSharedMemory

NdisMGetDmaAlignment

NdisMIndicateReceiveNetBufferLists

NdisMSetMiniportAttributes

NdisSystemProcessorCount