我下载了WinDDK,并使用ndisprot 5x从我的用户应用程序广播原始以太网数据包,指定目标MAC所有0xff,在大型和重复的数据集上,它似乎不是很有效。
目前工作的是环回-指定目标和源MAC作为我自己的,我得到所需的速度,但数据包永远不会离开我的网卡。
也许我错过了一些ndis驱动程序选项,并等待广播完成使用这个示例MS驱动程序?我想要的只是把数据包广播到网络上,我真的不关心传输状态,只想尽快摆脱它。
只有2个点的系统会有帮助吗?
在内核模式下不可能消除发送完成路径。原因是网卡忙于从内存中读取字节,直到它最终发出send-completion。如果在重用数据包之前没有等待发送完成,那么网卡就没有机会读取完整的数据包。你最终会发送损坏的数据。
但是,你是对的,当使用库存NDISPROT样本发送大量数据时,效率很低。问题是NDISPROT的用户模式示例应用程序同步地将数据写入kernelmode 。这意味着线程开始写(发送数据包),然后阻塞,直到写(发送数据包)完成。(这个示例是低效的,因为NDISPROT示例的重点是说明如何在内核模式下与NDIS进行互操作,而不是说明用户-内核通信的复杂技术。)
您可以使用以下几种技术中的一种来同时发出多个数据块,从而大大加快此速度:
-
使用多线程。执行与现在相同的操作,只不过是在多个线程上并行执行。这很容易设置,但它不能很好地扩展(要扩展到10倍的流量,您需要10倍的线程,然后您开始在缓存问题上受到伤害)。另外,如果你的数据集必须按顺序发送,你需要一堆复杂的同步来确保线程按顺序发出请求。
-
使用WriteFile和OVERLAPPED数据结构的异步调用。这需要您对用户模式应用程序进行一些重新配置(幸运的是,您不需要触摸内核驱动程序,因为内核驱动程序已经支持此操作)。使用OVERLAPPED写,您可以从单个线程发出多个并发写,然后在任何(或全部)写完成时得到通知。如果您对重叠设计足够小心,您应该能够轻松地填充100Mbps的网络链接。
更明确地说,这是你目前拥有的:
Your app NDISPROT driver Network card The network
---------------------------------------------------------------------------------
WriteFile
. -------> NdisProtWrite
. -------> NdisSendPackets
. |
. (copy packet payload
. from system RAM to
. network card's buffer)
. |
. |---------------> Start sending
. NdisProtSendComplete <---------| .
WriteFile <----/ | .
returns |<--------------- Finish sending
正如你所看到的,你的用户模式应用程序被卡在WriteFile的整个时间,网卡复制数据包有效载荷从RAM到网卡硬件。相反,如果您使用异步写入内核模式,您将得到如下结果:
Your app NDISPROT driver Network card The network
---------------------------------------------------------------------------------
WriteFile
. -------> NdisProtWrite
. | -------> NdisSendPackets
WriteFile <------/ |
returns (copy packet payload
from system RAM to
network card's buffer)
|
|---------------> Start sending
NdisProtSendComplete <---------| .
Async write <--/ | .
completes |<--------------- Finish sending
在这种设置中,WriteFile返回得更快,因此您有机会在NIC仍在读取第一个数据包时将另一个数据包(或10个)排队。您可以使用任何常用的OVERLAPPED技术来确定写(发送数据包)何时完成,并且您可以重用数据缓冲区。
要开始异步I/O,请从本文档开始。(哎呀,看起来他们的图表被旋转了90度;