Mic*_*_73 5 networking udp tcp low-latency
这只是我一直想知道的一些高性能计算的一般性问题.某个低延迟消息传递供应商在其支持文档中讲述了如何使用原始套接字将数据直接从网络设备传输到用户应用程序,这样做可以说明减少消息传递延迟甚至比无论如何还要多(在其他情况下)经过深思熟虑的设计决策).
因此,我的问题是那些在Unix或类Unix系统上浏览网络堆栈的人.他们可能能够实现这种方法有多大差异?您可以随意回忆记忆副本,获救的鲸鱼数量或威尔士面积;)
根据我的理解,他们的消息是基于UDP的,所以建立TCP连接等没有问题.感谢这个主题的任何其他兴趣点!
最好的祝愿,
麦克风
在Google 上搜索了一些图片http://vger.kernel.org/~davem/tcp_output.htmltcp_transmit_skb(),它们是 tcp 数据路径的关键部分。他的网站上有一些更有趣的东西http://vger.kernel.org/~davem/
在数据路径的user - tcp 传输部分,有1 个从用户到 skb 的副本skb_copy_to_page(通过 发送时tcp_sendmsg())和0 个副本(通过 do_tcp_sendpages调用tcp_sendpage())。需要复制来保留数据备份,以防未交付段的情况。内核中的 skb 缓冲区可以被克隆,但它们的数据将保留在第一个(原始)skb 中。Sendpage 可以从其他内核部分获取一个页面并保留它进行备份(我认为有像 COW 这样的东西)
调用路径(从 lxr 手动)。发送tcp_push_one/__tcp_push_pending_frames
tcp_sendmsg() <- sock_sendmsg <- sock_readv_writev <- sock_writev <- do_readv_writev
tcp_sendpage() <- file_send_actor <- do_sendfile
Run Code Online (Sandbox Code Playgroud)
收到tcp_recv_skb()
tcp_recvmsg() <- sock_recvmsg <- sock_readv_writev <- sock_readv <- do_readv_writev
tcp_read_sock() <- ... spliceread for new kernels.. smth sendfile for older
Run Code Online (Sandbox Code Playgroud)
在接收中,可以有1 个从内核到用户的副本skb_copy_datagram_iovec(从 调用tcp_recvmsg)。对于 tcp_read_sock() 来说,可以有副本。它会调用sk_read_actor回调函数。如果它对应于文件或内存,它可能(也可能不)从 DMA 区域复制数据。如果是其他网络,它有一个接收到的数据包的 skb,并且可以就地重用其数据。
对于 udp - receive = 1 copy -- 从 udp_recvmsg 调用 skb_copy_datagram_iovec。Transmission = 1 copy -- udp_sendmsg -> ip_append_data -> getfrag (似乎是 ip_generic_getfrag,有 1 个来自用户的副本,但可能是一个没有页面复制的 smth sendpage/splicelike。)
一般来说,从用户空间发送/接收到用户空间时必须至少有 1 个副本,而在使用内核空间源/目标缓冲区数据的零复制(惊讶!)时必须有 0 个副本。所有标头均在不移动数据包的情况下添加,启用 DMA 的(所有现代)网卡将从启用 DMA 的地址空间中的任何位置获取数据。对于古老的卡,需要PIO,因此会多一份副本,从内核空间到PCI/ISA/smthelse I/O寄存器/内存。
UPD:在从NIC(但这与NIC相关,我检查了8139too)到tcp堆栈的路径中,还有一份副本:从rx_ring到skb,对于接收也是如此:从skb到tx buffer +1copy。您必须填写 ip 和 tcp 标头,但是 skb 是否包含它们或它们的位置?
| 归档时间: |
|
| 查看次数: |
600 次 |
| 最近记录: |