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

时间:2009-12-01 18:05:33

标签: linux sockets asynchronous

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

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

谢谢!

2 个答案:

答案 0 :(得分:19)

最近关于linux-kernel的一些关于为这些内容提供API的讨论,但关键是你无法从一般用户空间缓冲区到网卡,因为:

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

在最近的内核上,您可以尝试一起使用vmsplicesplice来实现您想要的内容 - vmsplice您想要发送到的页面(SPLICE_F_GIFT)管道,然后splice他们(SPLICE_F_MOVE)从管道进入套接字。

答案 1 :(得分:1)

如果你不能使用sendfile(2),那么AFAIK你正在使用最有效的调用。 The C10K problem

涵盖了高效高性能网络代码的各个方面