我一直在读关于NIC捕获数据包后会发生什么,我读的越多,我就越困惑。
首先,我已经读过传统上,在NIC捕获数据包之后,它被复制到内核空间中的内存块,然后被复制到用户空间,以用于随后处理数据包数据的任何应用程序。然后我读到了DMA,其中NIC直接将数据包复制到内存中,绕过CPU。 NIC也是如此 - >内核内存 - >用户空间内存流仍然有效?此外,大多数NIC(例如Myricom)是否使用DMA来提高数据包捕获率?
其次,RSS(接收端扩展)在Windows和Linux系统中的工作方式是否相似?我只能找到关于RSS如何在MSDN文章中工作的详细解释,他们在这里讨论RSS(和MSI-X)如何在Windows Server 2008上运行。但RSS和MSI-X的相同概念仍应适用于Linux系统,对吧?
谢谢。
此致 莱恩
答案 0 :(得分:14)
这个过程如何发挥主要取决于驱动程序作者和硬件,但对于我看过或写过的驱动程序以及我使用的硬件,这通常是它的工作方式:
内核中的零拷贝网络并不是那么糟糕。零拷贝一直到用户区是很多更难。 Userland获取数据,但网络数据包由标头和数据组成。至少,真正的零拷贝一直到用户区需要来自NIC的支持,以便它可以将数据包DMA分成单独的头/数据缓冲区。一旦内核将数据包路由到目的地并且验证校验和(对于TCP,如果NIC支持它,则在硬件中,或者如果不支持,则在软件中),标题将被回收;请注意,如果内核必须自己计算校验和,则需要也可以复制数据:查看数据导致缓存未命中并将其复制到其他地方可以免费使用调优代码。)
即使假设所有星星都对齐,当系统收到数据时,数据实际上并不在您的用户缓冲区中。在应用程序请求数据之前,内核不知道它将在何处结束。考虑像Apache这样的多进程守护进程的情况。有许多子进程,都在同一个套接字上侦听。您还可以建立连接fork()
,这两个进程都可以recv()
传入数据。
进一步考虑用户缓冲区。这些是由应用程序分配的。为了完全用于零拷贝,缓冲区需要页面对齐,不要与其他任何内容共享该内存页面。在recv()
时,内核理论上可以用包含数据的页面重新映射旧页面并将其“翻转”到位,但由于上面的重组问题,这很复杂,因为连续的数据包将位于不同的页面上。内核可以将数据限制回每个数据包的有效负载,但这意味着需要进行大量额外的系统调用,页面重新映射以及总体上较低的吞吐量。
我真的只是在谈论这个话题。我在21世纪初曾在几家公司工作,试图将零拷贝概念扩展到用户区。我们甚至在userland中实现了一个TCP堆栈,并完全为使用堆栈的应用程序规避了内核,但这带来了一系列问题并且从未产生过生产质量。这是一个非常难以解决的问题。
答案 1 :(得分:0)
看看这篇论文,http://www.ece.virginia.edu/cheetah/documents/papers/TCPlinux.pdf它可能有助于清除一些内存管理问题