最近一直在看进程间通信(IPC),下面将做个小结:
其实这里分为两种,第一种是进程与进程之间的共享,线程与线程之间的共享,那么也就分为了进程之间的(IPC)与线程之间的(IPC)。
一、进程之间(IPC)
进程之间的通信有以下几种:
1、管道,FIFO
2、信号
3、消息队列
4、信号量(一般用于同步、互斥)
5、共享内存
6、socket
补充:
- 随进程持续:IPC一直存在到打开IPC对象的最后一个进程关闭该对象为止。如管道和有名管道;
- 随内核持续:IPC一直持续到内核重新自举或者显示删除该对象为止。如消息队列、信号灯以及共享内存等;
- 随文件系统持续:IPC一直持续到显示删除该对象为止。
它们之间的优缺点:
管道:
1、管道是半双工的,需要双方通信时,需要建立起两个管道;
2、只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
3、管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中;
4、数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
缺点:
- 只支持单向数据流;
- 只能用于具有亲缘关系的进程之间;
- 没有名字;
- 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小);
- 管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等;
FIFO:
与管道差不多,只是弥补了管道只能在亲缘关系的进程之间,FIFO可以用于任何进程之间。
管道及有名管道则是典型的随进程持续IPC,并且,只能传送无格式的字节流无疑会给应用程序开发带来不便,另外,它的缓冲区大小也受到限制。
信号:
异步中断。信号这种通信方式更像"即时"的通信方式,它要求接受信号的进程在某个时间范围内对信号做出反应,因此该信号最多在接受信号进程的生命周期内才有意义,信号所传递的信息是接近于随进程持续的概念。
消息队列:
消息队列是随内核持续的。
它提供有格式字节流,有利于减少开发人员的工作量;其次,消息具有类型,在实际应用中,可作为优先级使用。,消息队列可以在几个进程间复用,而不管这几个进程是否具有亲缘关系。消息队列是随内核持续的,与有名管道(随进程持续)相比,生命力更强,应用空间更大。
信号量:
它主要提供对进程间共享资源访问控制机制。系统V信号灯是随内核持续的,只有在内核重起或者显示删除一个信号灯集时,该信号灯集才会真正被删除。
共享内存:
采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据. 系统V则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信。
二、线程之间(IPC)
其实线程之间本来就是共享的,直接就可以通信的,更重要的是实现他们之间的同步与互斥。
其中有一下几种方式:
互斥锁;如果此时想利用互斥锁来达到不同进程之间的共享的话,那么如果简单的将该互斥锁设定属性为PTHREAD_PROCESS_SHARED也不行,这个时候还必须将该互斥锁对象创建在共享内存中。
读写锁,自旋锁;
条件变量。