Linux下的进程通信方式

Linux下的六种进程间通信方式简述

Linux中的IPC的分类

  • 通信:关注进程之间的数据交换
  • 信号;在特殊情况下可以用作同步技术,甚至可以将其当作一种通信技术
  • 同步:各个线程、进程之间的同步

为什么会有如此多的IPC方式?

  • 历史原因,不同的工具在不同的 UNIX 实现上各自进行演化,随后被移植到了其他 UNIX 系统上。
  • 为了适应多种应用场景,不同IPC方式被设计出来,以满足用户的需求。

通信方式

由上面的图可以知道,通信主要被分为了两大类:

  • 数据传输:通过两次用户空间与内核空间的交互来达到数据传输的目的。
  • 共享内存:将数据存储在一块共享的内存中,因此这个方式的通信是不需要进行系统调用的,这使得内存内存这一类数据传输的方式在效率上要比其他方式高很多。

数据传输

其中数据传输有被分为了一下几类:

  • 字节流:每次读取都可以读写任意多个字节的数据
  • 伪终端:一种在特殊情况下使用的数据传输方式。
  • 消息:每次只可以读或写一条消息,并且无法一次写多个消息,或者是一次读多个消息,也不可以留下数据在IPC中

同步方式

Linux主要提供的同步方式有:

  1. 信号量
  2. 文件锁
  3. 互斥量
  4. 条件变量

通信工具也可以用来进行同步。

Linux下的六种进程间通信方式

  1. 信号
  2. 信号量
  3. 管道
  4. 消息队列
  5. 套接字
  6. 共享内存

信号

Linux系统定义了大量信号,比如说:SIGINIT SIGKILL SIGHUP等等

信号用以进行进程之间的通讯,通知接收进程某个事件已经发生。

管道

管道(pipe)还包含有名管道(FIFO)、流管道(s_pipe)。

pipe

这是最基础的无名管道,其特点是只可以用于有亲缘关系之间的进程进行通信,并且还是只可以进行半双工(一次性只可以接受或者是发送数据)

无名管道简单方便.但局限于单向通信的工作方式.并且只能在创建它的进程及其子孙进程之间实现管道的共享

s_pipe

流管道使得管道可以进行全双工通信

FIFO

有名管道使得管道可以进行无亲缘关系的进程之间的通信。

有名管道虽然可以提供给任意关系的进程使用.但是由于其长期存在于系统之中,使用不当容易出错.所以普通用户一般不建议使用。

信号量(semophore)

信号量其实是一种同步机制,其是一个计数器。有二元信号量,三元,N元等等。

套接字(socket)

套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信

消息队列

消息队列是有消息组成的,其是消息的队列。其克服了消息传递的消息少,管道只可以承受无格式字节流和受限于缓冲区大小的限制。

消息缓冲可以不再局限于父子进程,而允许任意进程通过共享消息队列来实现进程间通信,并由系统调用函数来实现消息发送和接收之间的同步,从而使得用户在使用消息缓冲进行通信时不再需要考虑同步问题,使用方便,但是信息的复制需要额外消耗CPU的时间,不适宜于信息量大或操作频繁的场合。

共享内存

共享内存就是内核映射一段能被其他进程所访问的内存。这段共享内存由一个进程创建,但多个进程都可以访问。

共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。

共享内存的通信方式是通过将共享的内存缓冲区直接附加到进程的虚拟地址空间中来实现的,因此,这些进程之间的读写操作的同步问题操作系统无法实现。必须由各进程利用其他同步工具解决。另外,由于内存实体存在于计算机系统中,所以只能由处于同一个计算机系统中的诸进程共享。不方便网络通信。

共享内存块提供了在任意数量的进程之间进行高效双向通信的机制。每个使用者都可以读取写入数据,但是所有程序之间必须达成并遵守一定的协议,以防止诸如在读取信息之前覆写内存空间等竞争状态的出现。

不幸的是,Linux无法严格保证提供对共享内存块的独占访问,甚至是在您通过使用IPC_PRIVATE创建新的共享内存块的时候也不能保证访问的独占性。 同时,多个使用共享内存块的进程之间必须协调使用同一个键值。

共享内存针对消息缓冲的缺点改而利用内存缓冲区直接交换信息,无须复制,快捷、信息量大是其优点。,所以大数据量,可以使用共享内存。

总结

  • 管道:速度慢,容量有限,只有父子进程能通讯

  • FIFO:任何进程间都能通讯,但速度慢

  • 消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题

  • 信号量:不能传递复杂消息,只能用来同步

  • 共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存

参考资料

https://www.cnblogs.com/wuyepeng/p/9747515.html

Linux-Unix系统编程


Linux下的进程通信方式
https://ysc2.github.io/ysc2.github.io/2023/11/10/Linux下的进程通信方式/
作者
Ysc
发布于
2023年11月10日
许可协议