0

我正在用 C# 开发一个需要网络访问的虚拟化应用程序。我正在使用 ndisprot 示例驱动程序来读取和写入以太网第 2 层数据包。我一切正常,除了 WriteFile 操作需要大量时间。通常在 300-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:我的驱动程序有两个线程——一个读线程和一个写线程。似乎如果我禁用我的阅读器线程,写入会立即完成。为什么读取文件会影响写入文件?

4

1 回答 1

1

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

您的用户模式代码可能以同步模式打开了句柄。在同步模式下,每个句柄一次只能服务 1 个调用,即使 2 个不同的线程在同一个句柄上工作。 更多在这里

解决方法是:

  • 打开N个句柄以获得N个同时操作;或者
  • OVERLAPPED在模式下打开手柄。如果你有使用 C# 编码的奢侈,你会使用FileOptions.Asynchronous.

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

NDISPROT 示例设计得非常简单。在 NIC完成数据包之前,它具有写入块。这就是为什么写入需要数百毫秒。此外,由于句柄是在同步模式下打开的,这意味着在第一个数据包完成之前,您不能发送第二个数据包。

对于任何严重的吞吐量来说,这都太慢了。你需要在某处引入异步。在此处查看更多讨论:原始以太网广播

于 2014-10-03T21:06:46.250 回答