NdisProt需要很长时间才能写入以太网数据包

时间:2014-10-03 04:46:51

标签: networking driver ethernet wdk ndis

我在C#中开发需要网络访问的虚拟化应用程序。我使用ndisprot示例驱动程序读取和写入以太网第2层数据包。除了WriteFile操作需要花费大量时间外,我的一切工作正常。通常在3到800毫秒之间,但有时需要几秒钟才能完成写入。

这是我的C#函数,它将以太网数据包写入驱动程序。我用秒表来衡量需要多长时间。

private Stopwatch sw = new Stopwatch();

/// <summary>
/// Writes a layer-2 Ethernet packet to the adapter
/// </summary>
/// <param name="packet">The packet data</param>
/// <returns>true if the write was successful</returns>
public bool WriteEnetPacket(byte[] packet)
{
   int bytesSent = 0;
   bool packetSent = false;

   // Copy the packet data to raw buffer
   IntPtr packetPtr = Marshal.AllocHGlobal(packet.Length);
   Marshal.Copy(packet, 0, packetPtr, packet.Length);

   sw.Restart();
   packetSent = WriteFile(this.handle, 
      packetPtr, 
      packet.Length,
      out bytesSent, 
      0);

   sw.Stop();
   Console.WriteLine("WriteFile completed in {0}ms", sw.Elapsed.Milliseconds);

   // Free the memory
   Marshal.FreeHGlobal(packetPtr);

   // check to see if packet was sent
   if (!packetSent)
   {
      var err = UnsafeMethods.GetLastError();
      var errStr = UnsafeMethods.GetLastErrorString();

      Console.WriteLine("ERROR: Packet not sent: 0 bytes written.");
      Console.WriteLine("Reason: " + errStr);
      return false;
   }

   // otherwise the packet was sent
   Console.WriteLine("Packet sent: " + bytesSent.ToString() + "bytes written");
   return true;
}

当我运行我的应用程序时,我的输出看起来像这样。我有线连接。

Packet sent: 42bytes written
WriteFile completed in 160ms
Packet sent: 42bytes written
WriteFile completed in 458ms
Packet sent: 74bytes written
WriteFile completed in 364ms
Packet sent: 74bytes written
WriteFile completed in 51ms
Packet sent: 86bytes written
WriteFile completed in 221ms
Packet sent: 74bytes written
WriteFile completed in 271ms
Packet sent: 74bytes written
WriteFile completed in 1ms
Packet sent: 74bytes written
WriteFile completed in 292ms

如果我ping我的应用程序,响应时间几乎完全匹配WriteFile完成所需的时间,所以我知道挂起是在驱动程序的某个地方。我可以在示例驱动程序中做些什么来加快速度吗?我做错了什么?

编辑:今天我尝试使用我的USB以太网适配器而不是内置适配器,性能更差!它需要15-30秒才能完成写作。这是最离奇的,因为阅读接近瞬间。

Edit2:我的驱动程序有两个线程 - 一个读线程和一个写线程。似乎如果我禁用我的读者线程,写入立即完成。为什么从文件中读取会影响写入?

1 个答案:

答案 0 :(得分:1)

为什么读取会减慢写入速度?

您的用户模式代码可能在同步模式下打开句柄。在同步模式下,即使两个不同的线程在同一个句柄上工作,每个句柄一次只能有1个服务。 More here

修复是:

  • 打开 N 句柄以获取 N 同时操作;或
  • OVERLAPPED模式打开句柄。如果您可以使用C#进行编码,则可以使用FileOptions.Asynchronous

为什么发送一个数据包需要200ms?

NDISPROT样本设计超级简单。它已写入块,直到NIC 完成数据包。这就是写入数百毫秒的原因。此外,由于句柄以同步模式打开,这意味着在第一个数据包完成之前,您无法发送第二个数据包。

对于任何严重的吞吐量来说,方式太慢了;你需要在某处介绍异步。在此处查看更多讨论:Raw ethernet broadcasting