当被问到进程间的通信方式有哪几种时,估计大脑瞬间发懵,这是全新的技术或名词吗?不是的,其实我们经常会用到进程的通信方式,只是我们一直没有注意到罢了。

进程间的通信方式,有以下几种:

  • 管道
  • 消息队列
  • 共享内存
  • 信号量
  • 信号
  • Socket

1、管道

管道分为匿名管道与命名管道。

(1)匿名管道

我们常用到的linux命令中的 “|” 就代表着一个匿名管道,将一个进程的执行结果输出到另外一个进程中。比如

netstat -lnp | grep port 这个命令是查看某个端口的占用情况

(-l 显示listen状态的端口,-n 拒绝显示别名,即将0.0.0.0:http显示为0.0.0.0:80,-p 显示相应的pid与程序名)

(如果提示命令不存在的话,请执行yum install -y net-tools)

匿名管道只能用于具有亲缘关系的进程之间的通信,半双工,即数据只从一个方向传输至另外一个方向。

(2)命名管道,也称作FIFO。

使用mkfifo <pipename>的命令用来创建一个命名管道。

此时该进程将hello写入到命名管道pipe中,并阻塞到别的进程从该管道中读取数据为止。一直没有读取,就一直阻塞。

下一个进程从该管道中读取后,第一个进程将会返回。

命名管道用于两个无关进程之间的通信,但会存在同步阻塞的情况。


2、消息队列

消息队列能够解决命名管道的阻塞问题,a进程向b进程传递消息时,只需要将消息放进消息队列中,然后立即返回,无需阻塞。

但是这种通信方式也有其缺点,如果a进程于b进程通信频繁,a进程需要从内存读取大量的数据到消息队列中,然后b进程需要从消息队列中拷贝大量的数据到内存中,这段过程相当耗费时间。


3、共享内存

系统在创建一个进程的时候,不是分配实际的物理内存,而是分配一个虚拟的内存空间。

各个进程的虚拟内存空间彼此独立,但只要两个进程各自拿出一段虚拟内存地址,映射到相同的一块物理内存中。此时两个进程有着相同一块的物理内存,即共享一段物理内存,可以有效解决消息队列的频繁拷贝的问题。


4、信号量

当多个进程同时操作一块临界资源时,就会发生竞争的问题,这种问题常常发生在共享内存中。

信号量和锁一样,用于多个进程之间的互斥与同步。

信号量本质是一个计数器,假设当前情况下,信号量的初始值为1。当a进程对临界资源进行操作时,判断信号量的值是否大于0,如果是,代表a进程有对该资源的操作权限,然后对信号量进行减1,此时信号量变为0。在a进程还没有释放该资源的情况下,b进程想对该资源进行操作,首先判断信号量的值是否大于0,此时信号量为0,代表b进程没有对该资源操作的权限。

只有当a进程释放资源时,信号量自动加1,b进程才可以对资源进行操作。

两个进程通过对信号量的判断,来判断是否可以操作临界资源,这种方式也算是进程间的通信方式。


5、信号

信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

有关信号的详细介绍,可以参考这篇文章几种常见进程间通信(IPC)方式之信号


6、Socket

以上几种通信方式使用在一台主机之间不同进程之间的通信,而Scoket用于不同主机之间的通信。

一个简单的Scoket通信例子,可以参考我的另外一篇文章使用Socket完成客户端与服务端的双向通信