进程间通信的五种方式原理及代码实现 进程间通讯IPC的几种方式的优缺点总结

进程通信的五种方式


在计算机系统中,进程之间有时需要进行数据的通信,但是不同进程之间的数据存储时相互隔离的,每一个进程只能访问自己占有的数据。
需要使用进程通信机制来实现。
除了套接字外,进程间通信的前提是两进程必须是父子进程关系,没有这种关系的进程间不能直接进行通信,而是需要利用其共同的父进程进行信息的中转。
15 进程通信与实现 - 图1

1. 管道

管道的**通信介质是文件,这种文件称为管道文件,两个进程利用管道文件进行通信时,一个进程为写进程,一个为读进程**。
写进程通过写端(发送端)往管道文件中写入信息;读进程通过读端(接收端)从管道文件中读取信息。两个进程协调不断的写读操作,便会构成双方通过管道传递信息的流水线。

匿名管道 pi’pepipe

匿名管道是半双工的,数据只能单向通信;需要双方通信时 需要建立两个通道;只能用于父子进程或者兄弟进程之间。

命名管道 fifo

提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样即使与FIFO的创建进程不存在亲缘关系的进程只要可以访问到该路径,就能够彼此通过FIFO通信。
因此通过FIFO,不相关的进程也能交换数据
值得注意的是:

FIFO严格遵循first in first out,对管道以及FIFO的读取总是从开始处返回数据,对他们的写则是将数据添加到末尾

2. 信号 signal

信号是一种比较复杂的通信方式,信号产生的条件:

  • 按键
  • 硬件异常
  • 进程调用kill函数将信号传递给另一个进程
  • 用户调用kill命令将信号发送给其他进程

信号传递的消息比较少,主要用于通知接受进程某个时间已经发生

3. 信号量 semophore

信号量是一个计数器,可以用来控制多个进程对共享资源的访问,它常作为一个机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此主要作为进程间以及进程内不同线程之间的同步手段。
主要用来解决进程和线程间的并发执行时的同步问题。进程同步是并发过程中为了完成共同任务采用某个条件来协调他们的活动,这是进程之间发生的一种直接制约关系。

对信号量的操作分为P操作和V操作

P操作——信号量-1 V操作——信号量+1 当信号量的值小于等于0时,再进行P操作当前进程或线程会被阻塞,知道另一个线程或者进程执行了V操作将信号量的值增加到大于0后。锁的实现原理之一。

信号量我们需要定义信号量的数量,设定初始值,以及决定何时进行PV操作。

4. 消息队列

消息队列是消息的链表,存放在内核中并由消息队列标识符标识,消息队列克服了信号传递少,管道只能承载无格式字节流以及缓冲区大小受限等特点。消息队列起到了信箱作用,到了就挂在那里,需要的时候去取。消息队列提供了一种在两个不想管进程间传递数据的简单有效方法。
优点:

  • 可以通过发送消息来几乎完全避免命名管道的同步和阻塞问题
  • 可以用一些方法提前查看紧急消息

缺点:

  • 与管道一样,每个数据块都有一个最大长度的限制
  • 系统中所有队列包含的全部数据块总长度也有上限

Linux系统中有两个宏定义:

  • MSGMAX: 以字节为单位,定义一个消息的最大长度
  • MSGMNB: 以字节为单位,定义一个消息队列的最大长度

5. 共享内存

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的IPC方式,它是针对其他进程间通信方式运行效率低而专门设计的。访问共享内存区域和访问进程独有的内存区域一样快,并不需要通过系统调用或者其它需要切入内核的过程来完成。同时它也避免了对数据的各种不必要的复制。共享内存块提供了在任意数量的进程之间进行高效双向通信的机制。每个使用者都可以读取写入数据,往往与其他通信机制,如信号量配合使用,来实现进程间的同步和通信。而它的局限性也在于此.即共享内存的诸进程必须共处同一个计算机系统.有物理内存可以共享才行。共享在共享大数据文件时有用,直接在相同进行内存的拷贝,速度快,效率高,需要考虑访问临界资源并发同步。共享内存区是最快的可用IPC形式,一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据的传递就不再通过执行任何进入内核的系统调用来传递彼此的数据,节省了时间。

共享内存和消息队列、FIFO、管道的消息传递区别:

消息队列、FIFO、管道的消息传递方式一般为:

  1. 服务器得到输入
  2. 通过管道、消息队列写入数据,通常从进程拷贝到内核
  3. 客户从内核拷贝到进程
  4. 然后再从进程中拷贝到输出文件

上述过程需要四次拷贝才能完成文件的传递
共享内存只需要:

  1. 从输入文件到共享内存区
  2. 从共享内存区输出到文件

不涉及内核的拷贝,所有花的时间较少

6. 输出套接字

进程间通信的一种方式是使用UNIX套接字sockaddr_un,人们在使用这种方式时往往用的不是网络套接字,而是一种称为本地套接字的方式。本地套接字用于本地进程间的通讯更安全和稳定。