4

网络是我在操作系统中最糟糕的领域,所以请原谅我问了一个不完整的问题。我已经阅读了几个小时,但它有点在我脑海中游泳。(对我来说,与弄清楚网络协议相比,我觉得芯片设计很容易。)

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

但是对于一个项目,我们正试图将它们全部压缩到基于 Atom Z530P 的动力不足的嵌入式“设备”中,因此在我看来,内存复制开销是我们可以优化的东西。我一直在这里阅读:data-link-access-and-zero-copyLinux_packet_mmappacket_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) 内核,因为我使用的是不提供 vmlinux 的 CentOS 6.2,所以我无法对其进行分析。我假设内核时间是空闲时间和数据复制的组合,仅此而已。

在此先感谢您的帮助!

4

2 回答 2

7

我是否使事情过于复杂和/或优化了错误的事情?

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

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

根本不会“忘记”这些信息。

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

不,你必须自己做。

于 2011-12-28T21:18:13.000 回答
2

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

正如@cnicutar 所说,使用零拷贝和文件的 TCP/IP 的最佳方式是 sendfile(2) 和 splice(2)。我认为有一种方法可以在没有这些的情况下享受零拷贝(如果你想将数据读入内存,而不是直接读入文件),但我不知道该怎么做。

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

于 2012-01-01T09:16:41.547 回答