高效的Linux套接字(DMA /零拷贝)

30 sockets linux asynchronous

我正在构建一个性能非常高的Linux服务器(基于epoll,非阻塞套接字和异步磁盘IO [基于io_submit/io_getevents/eventfd]).我的一些基准测试表明,我处理套接字的方式不足以满足我的要求.特别是,我关心的是将数据从用户空间缓冲区传输到网卡,从网卡返回到用户空间缓冲区(现在让我们忽略sendfile调用).

根据我的理解,在非阻塞Linux套接字上调用读/写并不是完全异步的 - 系统调用阻塞,同时将缓冲区从用户空间复制到内核(或者反过来),然后才返回.有没有办法避免在Linux中听到这种情况?特别是,我是否可以在一个立即返回的套接字上进行完全异步写入调用,必要时将用户空间缓冲区DMA发送到网卡,并发出信号/设置事件/等.在结束的时候?我知道Windows有一个接口,但我在Linux中找不到任何相关的东西.

谢谢!

caf*_*caf 19

最近在Linux内核上有一些关于为这些内容提供API的讨论,但关键是你不能从一般用户空间缓冲区到网卡,因为:

  • 在用户空间线性地址空间中看起来像连续数据的东西在物理内存中可能是不连续的,如果网卡不进行分散 - 聚集DMA,这就是一个问题.
  • 在许多机器上,并非所有物理内存地址都是"DMA-able".目前,用户空间应用程序无法专门请求具有DMA功能的缓冲区.

在最近的内核,你可以尝试使用vmsplice,并splice共同实现你想要的- vmsplice在页(SPLICE_F_GIFT您想发送到管道中),然后splice他们(与SPLICE_F_MOVE从管道)插入插座.

  • @KarolyHorvath自你的评论和拼接和vmsplice 2.5年后仍然运行相当简洁的文档(每个半人手册页). (4认同)
  • 谢谢!您是否有预感这在读/写方面的效率如何?一般来说,是否有针对此类内容的“最佳实践”指南?我花了几天时间筛选所有轮询和信号 API,然后更多时间对其进行基准测试,然后我才找到多路复用套接字和异步 IO 的最佳实践。找到套接字最佳实践指南真的很有帮助。有 C10K 问题页面,但是那里的大部分信息已经有很多年了(这是内核时间的年龄),并且通常非常不确定。 (2认同)
  • `splice`和朋友是相当新的,所以我不确定是否有任何类型的"最佳实践"指南.在可能的情况下,它们应该具有相当低的延迟和零拷贝 - 这就是它们的全部要点.您可以尝试询问linux-net和/或linux-kernel邮件列表. (2认同)
  • 自这些职位过去1.5年后,这一领域的任何新发展?@caf:你能用`splice`做到这一点吗? (2认同)

Ron*_*nes 1

AFAIK 如果您不能使用 sendfile(2),那么您正在使用最有效的调用。C10K 问题涵盖了高效高性能网络代码的各个方面