我刚读到一个解释零拷贝机制的文章。
它讨论了零拷贝与无散射/聚集支持之间的区别。
不支持SG的网卡,数据副本如下

网卡与SG支持,数据副本如下

总之,在SG支持下,零拷贝可以消除一个CPU副本.
我的问题是为什么内核缓冲区中的数据可能是分散的
发布于 2012-03-19 13:50:48
因为Linux内核的映射/内存分配工具在默认情况下将创建几乎连续但可能物理上不相交的内存区域。
这意味着从sendfile()内部读取的文件系统进入内核虚拟内存中的缓冲区,DMA代码必须“转换”(因为没有更好的单词)到网卡的DMA引擎可以摸索的东西。
由于DMA (通常但并不总是)使用物理地址,这意味着您要么复制数据缓冲区(将其复制到一个专门分配的物理连续内存区域,即上面的套接字缓冲区),要么将其按时间传输一个物理页面。
另一方面,如果DMA引擎能够将多个物理上不相交的内存区域聚合成单个数据传输(称为“分散收集”),那么您可以传递物理地址列表(指向内核缓冲区的物理连续子段,即上面的聚合描述符),并且不再需要为每个物理页面启动单独的DMA传输。这通常是更快的,但它是否可以完成取决于DMA引擎的能力。
发布于 2012-03-19 17:06:25
我的问题是,为什么内核缓冲区中的数据会被分散?
因为它已经是,是分散的。TCP套接字前面的数据队列不被划分为将输出到网络接口上的数据报。分散允许您将数据保存在它所在的位置,而不必复制它来生成硬件可以接受的平面缓冲区。
通过收集功能,您可以为网卡提供一个数据报,该数据报在内存中的不同地址被分解为碎片,可以是对原始套接字缓冲区的引用。卡将从这些位置读取它,并作为一个单一的单位发送。
没有are (硬件需要简单的线性缓冲区),数据报就必须准备成一个连续分配的字节字符串,并且属于它的所有数据都必须是memcpy-d,从排队在套接字上传输的缓冲区进入位置。
发布于 2012-03-19 20:30:20
因为当您写入套接字时,数据包的报头被组装在与用户数据不同的位置,因此要合并成网络数据包,设备需要“收集”功能,至少要获取报头和数据。
另外,为了避免CPU不得不读取数据(因此,用它再也不需要的无用的东西填充它的缓存),网卡还需要生成自己的IP和TCP校验和(我在这里假设是TCP,因为99%的大容量数据传输将是TCP)。这没什么,因为现在他们都可以。
我不确定的是,这一切是如何与TCP_CORK交互的。
大多数协议都有自己的标头,因此假设的协议如下:
Client:发送请求服务器:发送一些元数据;发送文件数据
因此,我们倾向于让服务器应用程序在内存中组装一些头,发出写(),然后是sendfile()-like操作。在本例中,我认为头仍然被复制到内核缓冲区中。
https://stackoverflow.com/questions/9770125
复制相似问题