一. 定义
进程间的通信(IPC, Inter-process communication)是指在不同进程间传播和交换信息。
二. 集中通信方式的总结
常见的进程间的通信方式有7种:
- 管道(pipe),又称无名管道
- 命名管道(FIFO)
- 消息队列(MessageQueue)
- 信号量(Semaphor)
- 共享内存(SharedMemory)
- 套接字Socket
- 信号(signal)
管道
管道可以分为两类:匿名管道和命名管道。
命令“|”其实就是匿名管道,表示把一个进程的输出传输到另一个进程,如:
echo "Happyjava" | awk -F 'j' '{print $2}'
# 输出 ava
另外,可以通过mkfifo 命令 创建一个命名管道,如:
mkfifo pipe_me
一个进程往管道输入数据,则会自阻塞并等待 别的进程从管道读取数据:
如上图所示,如果右图没有执行 cat < pipe_me命令,则左边的窗口会一直阻塞。当先执行右侧的 cat < pipe_me命令,而没有执行左侧的 echo ‘happeyjava’ > pipe_me 命令,则右边的窗口会一直阻塞。
-
通过上边的实验,可知:命名管道 是连接 输入进程与读取进程的通道,完成一次信息读取之后,输入进程 和 读取进程才会结束阻塞状态。
-
通过vi 命令查看pipe_me文件,会发现其中没有输入的字符。可知 命名管道只是暂时的信息通道,而不是存储信息的文件。
消息队列
注意,这里的消息队列不是我们常用的MQ, 如kafaka, rabbitmq, rocketmq等。
消息队列提供了一种从一个进程发送一个数据块的方法。每个数据块,都被认为含有一个类型,接收进程可以独立地接受含有不同类型地数据结构。我们可以通过发送消息来避免命名通道地同步和阻塞问题。但是消息队列与命名通道一样,每个数据块都有一个最大长度的限制。
使用消息队列进行进程间的通信,可能会受到数据块最大长度的限制约束等,这也是这种通信方式的缺点。如果频繁的发生进程间的通信行为,那么进程需要频繁的读取队列中的数据到内存,相当于间接的从一个进程拷贝到另一个进程,这需要花费时间。
共享内存
共享内存这个通信方式 就可以很好地解决拷贝所消耗的时间了。系统加载一个进程的时候,分配给进程的内存并不是实际物理内存,而是虚拟内存空间。 那么我们可以让两个进程各自拿出一块虚拟地址空间来,然后映射到相同的务理内存中,这样,两个进程虽然有着独立的虚拟内存空间,但有一部分确实映射到相同的物理内存,这就完成了内存共享机制了。
信号量
共享内存最大的问题是什么? 没错 ,就是多进程竞争内存的问题,就类似于我们平时说的线程安全问题。而信号量,就是来解决这个问题。
信号量的本质就是一个计数器,用来实现进程之间的互斥与同步。例如信号量的初始值是1,然后 a 进程来访问内存1的时候,我们就把信号量的值设为0,然后进程b 也要来访问内存1的时候,看到信号量的值为0 就知道已经有进程在访问内存1了,这个时候 进程b 就会访问不了 内存1。所以说,信号量也是进程之间的一种通信方式。
Socket
定义:套接字(socket)用于协调不同的进程间的通信,可以是不同计算机上的进程。套接字通信方式很多,有Unix域套接字、TCP套接字、UDP套接字、链路层套接字等等。最常用的时TCP套接字。
信号
概念:
1)信号是在软件层上对中断机制的一种模拟,是一种异步通信方式。
2)信号可以直接进行用户控件进行和内核进程之间的交互,内核进程也可以利用它通知用户空间进程发生了哪些系统事件。
3)如果该进程当前并未处于执行态,则该信号就由内核保护起来,知道该进程恢复执行再传递给它;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。
还有一篇关于各通信方式的详细总结:
链接:https://www.jianshu.com/p/e0ea38ec4227