Linux 套接字 : Zero-copy local, TCP/IP 远程

标签 linux sockets zero-copy

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

我有一些通过套接字相互通信的网络服务。具体来说,套接字是使用 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为了传输数据。据我了解,由于套接字是本地的,因此您不需要可靠的“流”类型套接字,因此原始套接字是合适的接口(interface),我猜测使用了环形缓冲区在页面粒度上,每个数据包(或数据报)都从页面边界开始。

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

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

在此先感谢您的帮助!

最佳答案

Am I over-complicating things and/or optimizing the wrong thing?

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

What's the simplest or best way to detect that the two processes are on the same machine?

只是不要“忘记”此信息。

Does Linux do any of this automatically, optimizing for processes running on the same machine?

不行,你必须自己做。

关于Linux 套接字 : Zero-copy local, TCP/IP 远程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8661411/

相关文章:

c - epoll_wait() 阻止打印到标准输出

java - 使用 Socket 实现 HTTP 服务器 - 如何让它永远运行?

linux connect()超时和syncookies

linux - Wget ANSI 错误

linux - 我们可以写入物理地址linux吗

c++ - 使用 C++ 获取 linux 机器的屏幕截图

Linux 零拷贝

java - FileChannel 零拷贝 transferTo 拷贝字节到 SocketChannel 失败

linux - 如何在 jenkins exec 命令中使用 sudo 命令