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

Tim*_*ler 4 sockets linux zero-copy

网络是我操作系统中最糟糕的区域,所以请原谅我提出一个不完整的问题.我已经读了几个小时了,但是我的脑子里有点游泳.(对我而言,与制定网络协议相比,我觉得芯片设计很容易.)

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

但对于一个项目,我们试图将它们全部压缩到基于Atom Z530P的功能不足的嵌入式"设备"中,因此在我看来,内存复制开销是我们可以优化的.我在这里一直在阅读:data-link-access-and-zero-copyLinux_packet_mmap以及packet_mmap.

对于这种情况,可以创建如下的套接字:fd = socket(PF_PACKET, PF_RAW, 0);.还有很多其他事情要做,比如分配环形缓冲区,对它们进行映射,将它们与套接字相关联等等.看起来你只能使用sendtorecvfrom传输数据.据我所知,由于套接字是本地的,你不需要一个可靠的"流"类型套接字,所以原始套接字是适当的接口,我猜测环形缓冲区是以页面粒度使用的,每个数据包(或数据报)从页面边界开始.

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

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

在此先感谢您的帮助!

cni*_*tar 7

我是否过度复杂化和/或优化错误的东西?

有可能.使用PF_PACKET套接字仅适用于专门的东西.你可能想看一下

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

根本不要"忘记"这些信息.

Linux是否会自动执行此操作,优化在同一台计算机上运行的进程?

不,你必须自己做.