今天抽空把Linux IPC (InterProcess Communication)总结一下.
在开发大型应用程序时,避免不了要使用到多个进程协作完成任务.在Linux中进程间通信主要有如下几种方式. 下文中将简单介绍这几种通信机制及其使用的范围.
按照一些书上的描述,一般分为2类: 基于文件系统 和 基于内核. 但我个人觉得, 可以分为3类: 和文件系统及内核无关, 基于文件系统, 基于内核. 和文件系统及内核无关是指直接使用发送信号来进行通信情形.
列表如下:
1. 和文件系统及内核无关: 信号及信号处理
2. 基于文件系统: 无名管道, 有名管道
3. 基于内核: 共享存储, 信号量, 消息队列
第一种情况中:
信号和信号处理,一般可以应用于先注册信号及信号处理函数,进程间直接发送信号给对方,对方收到信号后由信号处理函数处理的情形.
第二种情况中:
无名管道,我们只讨论半双工无名管道,因为有一些系统对全双工无名管道支持不太好,暂不讨论. 半双工无名管道一般只能应用于有直接关系的进程间通信,例如,父子进程间,兄弟进程间. 它使用2个文件标识符标识读入端和读出端. 通信的双方只需要控制好使用的一个端口,关闭掉另外一个端口,即可直接通信,对半双工无名管道的读写操作和读写普通文件内容一样,使用read(),write()即可.无名管道因为在文件系统中没有对应的文件,所以只是内存中的一种资源,不能使用文件操作命令(如vim编辑器)查看内容.
有名管道,我们也只讨论半双工有名管道,因为有一些系统对全双工有名管道支持不太好,暂不讨论.半双工有名管道和半双工无名管道的有2个主要差别:可以在任意进程间通信,并且有实体文件与之对应,及可以通过文件操作命令(如vim编辑器)查看内容. 但是有名管道文件使用前必须先创建管道文件,一般我们是使用mkfifo来创建管道文件,管道文件和普通文件可以读取mask值分析来区别,并且管道文件内容读取走后,管道中的内容也消失掉了.
第三种情况中:
共享存储, 信号量, 消息队列是基于内核的机制,所以必须依赖内核中特殊的数据结构和特定系统调用接口,具体参见相关参考书.
共享存储,在没有提及共享存储(也叫共享内存)机制之时,一般而言,进程间的进程空间是相互独立的,任何进程不可以访问到其他进程空间的资源,这个是内核实现的保护机制. 有了共享存储机制后,进程间就可以通过调用相应函数实现进程间共享内存,在共享内存的地方交换信息进行通信.涉及到的具体函数和使用方法参见相关参考书. 可以使用ipcs -m查看系统中当前的共享存储情况.
信号量,其实只是一个锁机制,它并不具备交换数据的功能. 进程间也可以通过一些特定系统调用接口来实现信号量, 利用操作这个信号量来进行进程间通信. 使用ipcs -s来查看系统中当前的信号量使用情况.
消息队列,是最灵活的一种进程间通信方式,使用情况也最为复杂,用到较多的系统调用接口. 通信的双方通过在队列中存入消息和读取消息来进行通信,读取消息时也很多选择来读取不同的消息.
可以使用ipcs -a 来查看共享存储, 信号量, 消息队列的使用情况.
最后,进程间通信要避免临界区问题,要使用到锁机制来保证数据交互的完整性和准确性.