Linux套接字:零拷贝本地,TCP/IP远程



网络是我在操作系统中最糟糕的地方,所以请原谅我问了一个可能不完整的问题。这篇文章我已经看了几个小时了,但我脑子里一直在想。(对我来说,我觉得芯片设计比找出网络协议更容易。)

我有一些通过套接字相互通信的网络服务。具体来说,套接字是用fd = socket(PF_INET, SOCK_STREAM, 0);创建的,它会自动获取TCP/IP。我需要这个作为基本情况,因为这些服务可能运行在不同的机器上。

但是对于一个项目,我们试图将所有这些都压缩到一个基于Atom Z530P的低功率嵌入式"设备"中,所以在我看来,内存复制开销是我们可以优化的。我一直在这里阅读:数据链接访问和零复制以及Linux_packet_mmap和packet_mmap。

在这种情况下,可以这样创建套接字:fd = socket(PF_PACKET, PF_RAW, 0);。还有很多其他的事情要做,比如分配环缓冲区,映射它们,把它们和套接字联系起来,等等。看起来你被限制使用sendtorecvfrom来传输数据。根据我的理解,由于套接字是本地的,因此不需要可靠的"流"类型套接字,因此原始套接字是合适的接口,并且我猜测环缓冲区是在页粒度上使用的,其中每个数据包(或数据报)从页边界开始。

在我花费大量时间进一步调查这个问题之前,我希望一些有帮助的人可以帮助我解决一些问题:

  • 我应该期望从零拷贝套接字中获得多少性能优势?我想上次我检查的时候,我们正在将最大从一个进程移动到另一个进程,最后移动到磁盘。在最基本的场景中,数据从捕获进程移动到一对多进程(其他进程可以监听流),再移动到写入磁盘的归档进程。不算磁盘和内部的东西,这是两跳。
  • Linux是否自动执行这些操作,优化在同一台机器上运行的进程?
  • 在任何情况下,我将有监听套接字在TCP端口。我可以使用它们在进程之间建立连接,但仍然可以使用零复制吗?换句话说,我可以使用AF_INET与PF_PACKET?
  • PF_PACKET与SOCK_RAW是零拷贝套接字的唯一有效配置吗?
  • 是否有任何好的示例代码在那里,将使用零复制与TCP/IP作为回退?
  • 什么是检测两个进程在同一台机器上的最简单或最好的方法?它们知道彼此的IP地址,所以我可以比较并使用不同的代码路径。有更简单的方法吗?
  • 我可以在基于包的套接字上使用write()和read()吗,或者这些只对流有效?(重写如何建立连接将比重写所有套接字代码更简单。)
  • 我是否过于复杂和/或优化了错误的东西?OProfiler告诉我,大部分CPU时间花在两个地方:(1)zlib,(2)内核,我不能分析,因为我使用的是CentOS 6.2,它不提供vmlinux。我假设内核时间是空闲时间和数据复制时间的组合,没有太多其他的。

提前感谢您的帮助!

我是不是把事情复杂化了,或者优化错了?

可能。使用PF_PACKET套接字仅用于专门的东西。你可能想看看

  • sendfile (2)
  • 接头(2)

检测这两个进程的最简单或最好的方法是什么在同一台机器上?

不要"忘记"这些信息。

Linux是否自动执行这些操作,优化进程在同一台机器上运行?

不行,你得自己做。

我认为TCP/IP和原始数据包之间的选择比零复制问题重要得多。如果需要可靠的基于流的通信,则需要TCP/IP(即AF_INET+PF_STREAM)。尝试在不可靠的数据包上实现可靠的流是非常复杂的,并且已经为您完成了。

使用TCP/IP零拷贝和零文件的最好方法是,如@cnicutar所说,sendfile(2)和splice(2)。我认为有一种方法可以享受零复制没有这些(如果你想读数据到内存,而不是直接到文件),但我不确定如何做到这一点。

此外,Centos是开源的,所以你可以通过下载源代码并编译它来获得vmlinux文件。

相关内容

  • 没有找到相关文章

最新更新