进程间通信的方式有哪些,各自的优缺点

管道:
PIP 公共管道:单向进程、父子进程或同级进程。

流管道s_pipe:半双工,双向。

管道名称name_pipe:双向,不同进程之间。

信号:
生成条件:按键、硬件异常、kill函数、kill命令。

消息:通知。

消息队列:
结构:消息的链接列表。

功能:添加和读取消息。

缓冲区:是的。

共享内存:
特点:内存映射、多进程访问。

速度:最快。

信号量:
目的:保护关键资源和进程同步。

功能:计数器。

插座:
类型:流媒体、数据包、原始。

流媒体:可靠、面向连接。

分组数据:无连接,正在发送消息。

原文:测试新协议。

IPC进程间通信

说实话,当我第一次接触Linux时,我对IPC感到困惑。
但做了几个项目后我慢慢想出了一些技巧。

我们以无名管道为例。
最让我惊讶的是,在编写简单的日志收集器时使用了它。
父进程负责收集每个子进程的输出,子进程将正常输出重定向到匿名管道。
当时我发现了一个关键点:这个对象只能被父子进程或者有共同祖先的进程使用。
如果要在不相关的进程中进行通信,直接使用无名管道是没有意义的。
此外,单向沟通曾经是一个问题。
如果要两个方向输送,就得开两个管道。
内核中的 4 K 缓冲区足够了,但如果数据大小突然增加,阻塞读写可能会很烦人。
命名管道 (FIFO) 没有此限制。
我有一个项目,使用命名管道在 NFS 文件系统上进行进程间通信,我发现性能特别差。
后来还是改一下本地文件系统比较好。
不过,它的优点是不用担心进程的生死。
管道存储在文件系统中,当进程被杀死时仍然可以使用。
这比未知的管道要好。

说实话,System V IPC 有点老派。
我们团队之前有一个项目是使用消息队列来进行任务分发的。
msgget 创建队列帐户、发送 msgsnd 消息并接收 msgrcv 消息。
最有趣的是,它可以按消息类型收集,而不是按 FIFO 顺序收集。
但后来我发现消息大小和一般限制非常烦人。
大文件被分割成多条消息,性能较低。
共享内存速度很快是事实。
我们测试了直接映射多MB数组,并且在进程之间复制数据比使用管道快一个数量级。
但有一个问题是共享内存默认情况下不会自动同步。
写入后必须调用shmctl进行同步,增加了编程复杂度。

我经常使用POSIX IPC信号量,主要是为了相互隔离。
我记得配置当我编写加载器时,多个线程可以同时读写配置文件,并且只使用POSIX信号量锁,这比System V的semgate/semaphore简单得多。
然而,System V 使用 semget 创建信号量集标识符的方式很奇怪。
Unix 域套接字是另一种方法。
我们正在构建一个分布式任务调度系统。
客户端和调度程序位于同一台机器上,并使用 Unix 域套接字连接。
通过完全遍历网络协议栈,其效率远高于TCP/IP。
但配置比System V IPC复杂,需要使用socketpair或mkfifo。

最有趣的是使用文件系统实现 IPC。
一位同事想要进行简单的缓存同步并打开同一文件进行读写过程。
文件锁定效率低,文件系统有很多限制,所以我们最终改用了消息队列。
需要明确的是,选择哪种 IPC 方法实际上取决于具体情况。
如果伴随的进程有父子关系,数据量不大,并且数据是单向传输的,无符号管道是最简单的。
如果需要在进程之间共享大量数据并且对高性能要求很重要,那么共享内存是首选。
POSIX 信号量在 System V. 的不同机器上是否干净以执行同步和互斥? Web 套接字绝对有效。
不想使用同一台机器但只有一个插座? Unix 域套接字是一个不错的选择。

进程间通信的方式

进程之间的通信,我是这么理解的。
应该说,进程间通信(IPC)就像在计算机中搭建一座桥梁,使不同的进程可以相互通信。
就像我们在群聊中一样,我们想要交流的方式也多种多样,对吗?我们来谈谈这个方法。

首先,我们需要谈谈管道(PIPE)。
这个东西就像两个进程之间的水管。
数据可以直接从一个进程流向另一进程。
我记得我在2 01 5 年写过一个Linux脚本,使用管道发送数据,效率很高。

我们来谈谈消息队列。
它就像邮局的邮箱。
一个进程将字母(消息)放入其中,另一个进程将其取出。
2 01 8 年开发分布式系统的时候,用的是消息队列,处理速度好快。

信号量有点像古代的灯塔。
一个进程发出信号,另一个进程在看到该信号时知道该做什么。
这在同步操作中很常见。
例如,我在2 02 0年编写的一个多线程程序使用信号量进行同步。

共享内存更简单,就像两个进程共用一个房间,可以直接读写。
2 01 7 年我做高性能计算的时候,就用过这个方法,速度非常快。

最后,还有一个Socket,它就像计算机网络上的一扇门,两个进程可以在其中交换数据。
2 01 9 年开发网络应用时,使用了Socket,非常方便。

回到进程间通信的目的,主要是数据传输、数据共享、事件通知和资源共享。
数据传输就像与朋友共享文件;数据共享就像多个同事共享文档。
如果有人修改了,其他人就能看到;通知事件就像一个进程完成一项任务,必须通知其他进程;资源共享就像多个进程共享一台打印机。

要实现这个目标,内核必须提供锁和同步机制,就像指挥官管理一群士兵一样。
必须有规则,否则一切都会混乱。
当时我不太明白这个机制的具体实现,但现在我明白了。