进程间通信

5
我正在寻找一些数据,以帮助我决定在Linux上两个独立进程之间进行通信哪种方式更好/更快:

  • TCP
  • 命名管道

哪个更糟糕:管道的系统开销还是TCP协议栈的开销?


更新的具体要求:

  • 只需要本地IPC
  • 大多数情况下是许多短消息
  • 不需要跨平台,仅限于Linux

1
我认为这并不需要单独回答,但在我看来,如果你在同一台机器上的不同进程之间通信,绝对没有理由使用TCP(当然,除非我漏掉了什么重要的东西)。 - shylent
11
TCP具有一个优点,即如果必要的话,将应用程序分离将变得非常简单。这可以看作是未来的投资。当然,除此之外,我同意你的观点。 - Carl Smotricz
哦,你指出了我的短视 :) 卡尔·斯莫特里兹先生,你的观点非常有道理! - shylent
我可以建议您将您的要求添加到问题中吗?例如跨平台/性能。我已根据收集到的评论更新了我的答案。 - jldupont
8个回答

4

过去,我常常使用本地域套接字来进行这种事情。我的库会判断其他进程是本地系统还是远程,并使用TCP/IP进行远程通信,使用本地域套接字进行本地通信。这种技术的好处在于对应用程序的其余部分来说,本地/远程连接是透明的。

本地域套接字使用与管道通信相同的机制,不具备TCP/IP栈开销。


你有关于这个的更多信息吗?有没有链接可以提供?你使用了哪个库? - brandstaetter
抱歉,这是我为雇主编写的一个库,无法提供链接。 - Richard Pennington
啊,我明白了。我会看看域套接字,听起来很有趣。谢谢! - brandstaetter
根据维基百科,Unix域套接字的正确名称是POSIX本地IPC套接字。 - Jaywalker

3

我认为你不需要担心开销问题(这将非常低)。你是否使用性能分析工具确保你的应用程序瓶颈很可能是TCP开销?

无论如何,正如Carl Smotricz所说,我会选择sockets,因为将来将非常容易将应用程序分离。


过去我们使用了共享内存(目前使用boost.interprocess来实现),但最终发现它带来的麻烦比它的价值更大。在回环上,套接字/TCP的开销肯定非常低,真的不值得担心。当然,要针对您特定的用例进行分析以确保。 - jkp

3
我在之前的帖子中讨论了这个问题。我必须比较套接字、管道和共享内存通信。管道肯定比套接字快(如果我没记错的话,可能是两倍的速度...当我回到工作时可以检查这些数字)。但这些测量只是针对纯通信的。如果通信只是整个工作的很小一部分,那么两种类型的通信之间的差异将是微不足道的。 编辑 以下是我几年前进行测试的一些数据。您的结果可能会有所不同(特别是如果我犯了愚蠢的编程错误)。在这个具体的测试中,同一台机器上的“客户端”和“服务器”来回传递100字节的数据。它进行了10,000次请求。在我撰写的文档中,我没有指出机器的规格,因此只有相对速度可能有任何价值。但是对于好奇的人,这里给出的时间是每个请求的平均成本:
  • TCP/IP: .067毫秒
  • 使用I/O完成端口的管道:.042毫秒
  • 使用重叠I/O的管道:.033毫秒
  • 具有命名信号量的共享内存:.011毫秒

我正在寻找非常快速的通信方式,用于短消息传递,以控制我的程序流程(即在每次迭代后,程序会询问是否可以继续)。 - brandstaetter
如果您使用TCP/IP,请确保关闭Nagle算法。 - Richard Pennington
对于短消息(尤其是如果有大量消息),管道可能会更快。而且,如果您想要额外的苦头,您可能可以通过使用简单的共享内存获得更快的速度。当我上班后,我会尝试记住管道与TCP/IP数字,并在此处提供它们。正如我在其他帖子中提到的那样,这是几年前的事了,但我认为相对速度现在应该是相似的。 - Mark Wilkins

2

使用TCP会增加更多开销 - 这将涉及将数据拆分成数据包,计算校验和和处理确认,而在同一台机器上的两个进程之间通信时都不需要。使用管道仅会将数据复制到一个缓冲区中。


开销真的那么大吗? - jkp
如果处理器只有100MHZ,那么开销会更大,而我经常在这个范围内工作。如果你的处理器在GHZ范围内并且不关心最高性能,那么可能不值得麻烦。 - Richard Pennington
开销并不是那么大——127.0.0.1的MTU通常相当大,因此它不必将其分成太多数据包——但它仍然比命名管道多几个步骤。更重要的问题是:您是否希望此通信在不同计算机之间进行?如果是这样,那么请使用套接字,因为命名管道在不同计算机之间根本无法工作。还有UNIX域套接字,它们可能像管道一样运行,同时像套接字一样工作。最后,命名管道的另一个优点是访问控制和命名空间(路径与IP/端口)。 - Mike D.
是的,我们已经使用套接字在机器之间进行通信了,我正在寻找本地管理进程和工作程序之间的通信。 - brandstaetter
我同意Unix域套接字(请参见我的答案)。它们在POSIX中被称为本地域套接字。 - Richard Pennington
我认为Linux不会计算或检查本地TCP连接的校验和(使用Wireshark - 每个本地IP帧的TCP校验和都是错误的)。 - MarkR

2

需要考虑两个问题:

  1. 连接设置成本
  2. 持续通信成本

TCP协议:

(1) 成本更高 - 需要进行三次握手以应对(潜在的)不可靠通道。

(2) 成本更高 - IP层开销(校验和等),TCP层开销(序列号、确认、校验和等),这些都是在同一台机器上不必要的,因为通道应该是可靠的,不会引入网络相关的损害(例如数据包重排序)。

但我仍然会选择TCP,只要有意义(即取决于情况),因为它很普遍(即易于跨平台支持),在大多数情况下开销不应该是问题(即进行性能分析,不要过早优化)。

更新:如果不需要跨平台支持并且强调性能,则使用命名/域管道,因为我相信平台开发人员将优化掉处理网络级别损害所需的不必要功能。


我理解:命名管道在性能方面肯定更低成本。 - jldupont

2
我不知道这是否适合您,但在Linux下,非常常见的进程间通信(IPC)方式是使用共享内存。实际上,它非常快速(我没有进行过性能分析,但这只是在RAM上共享数据并进行强大处理)。
这种方法的主要问题是信号量,您必须围绕它构建一个小系统,以确保一个进程在另一个进程尝试读取时不会同时写入。
一个非常简单的入门教程在这里
这不像使用套接字那样具有可移植性,但概念是相同的,因此如果您将其迁移到Windows,则只需更改共享内存创建/附加层即可。

+1:我在MS Windows中使用共享内存进行IPC已经有一段时间了。它的效果非常好;唯一需要注意的是,共享内存有点像固定大小的数组;因此您必须有一种机制来同步不同进程对其的访问。 - Jaywalker
只是另一个评论,在 Windows 下,您可以在 MSDN 上搜索 CreateFileMapping/OpenFileMapping 和 MapViewOfFile。 - Douglas L

1

Unix域套接字是一个非常好的折衷方案。它没有TCP的开销,但比管道解决方案更具发展性。你没有考虑的一点是,套接字是双向的,而命名管道是单向的。


0

我认为管道会更轻一些,但这只是我的猜测。

但由于管道是一个本地事物,所涉及的代码可能要简单得多。

其他人可能会告诉你尝试测量两者以找出答案。这个回答很难出错,但你可能不愿意投入时间。那就只能希望我的猜测是正确的 ;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接