Linux进程间通信方式--信号,管道,消息队列,信号量,共享内存
1、概述
通信方法 | 无法介于内核态与用户态的原因 |
管道(不包括命名管道) | 局限于父子进程间的通信。 |
消息队列 | 在硬、软中断中无法无阻塞地接收数据。 |
信号量 | 无法介于内核态和用户态使用。 |
内存共享 | 需要信号量辅助,而信号量又无法使用。 |
套接字 | 在硬、软中断中无法无阻塞地接收数据。 |
2、信号
信号又称软终端,通知程序发生异步事件,程序执行中随时被各种信号中断,进程可以忽略该信号,也可以中断当前程序转而去处理信号,引起信号原因:
1).程序中执行错误码;
2).其他进程发送来的;
3).用户通过控制终端发送来;
4).子进程结束时向父进程发送SIGCLD;
5).定时器生产的SIGALRM;
3、管道
单向,一段输入,另一端输出,先进先出FIFO。管道也是文件。管道大小4096字节。
特点:管道满时,写阻塞;空时,读阻塞。
分类:普通管道(仅父子进程间通信)位于内存;命名管道位于文件系统,没有亲缘关系管道只要知道管道名也可以通讯。
管道是由内核管理的一个缓冲区(buffer),相当于我们放入内存中的一个纸条。管道的一端连接一个进程的输出。这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管道可以被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都终结的时候,管道也自动消失。
4、消息队列
消息队列是先进先出FIFO原则
消息结构模板
strut msgbuf{
long int mtype;//消息类型
char mtext[1];//消息内容
}
5、共享内存
共享内存的几乎可以认为没有上限,它也是不局限与父子进程,采用跟消息队列类似的定位方式,因为内存是共享的,不存在任何单向的限制,最大的问题就是需要应用程序自己做互斥,有如下几种方案
1 只适用两个进程共享,在内存中放一个标志位,一定要声明为volatile,大家基于标志位来互斥,例如为0时第一个可以写,第二个就等待,为1时第一个等待,第二个可以写/读
2 也只适用两个进程,是用信号,大家等待不同的信号,第一个写完了发送信号2,等待信号1,第二个等待信号2,收到后读取/写入完,发送信号1,它不是用更多进程是因为虽然父进程可以向不同子进程分别发送信号,但是子进程收到信号会同时访问共享内存,产生不同子进程间的竞态条件,如果用多块共享内存,又存在子进程发送结果通知信号时,父进程收到信号后,不知道是谁发送,也意味着不知道该访问哪块共享内存,即使子进程发送不同的结果通知信号,因为等待信号的一定是阻塞的,如果某个子进程意外终止,父进程将永远阻塞下去,而不能超时处理
3 采用信号量或者msgctl自己的加锁、解锁功能,不过后者只适用于linux
6、信号量
信号量是一种用于提供不同进程间或一个进程间的不同线程间线程同步手段的原语,systemV信号量在内核中维护
二值信号量 : 其值只有0、1 两种选择,0表示资源被锁,1表示资源可用;
计数信号量:其值在0 和某个限定值之间,不限定资源数只在0 1 之间;
计数信号量集 ;多个信号量的集合组成信号量集
------总结
管道是最弱的,只适合有限场景;
消息队列能适合大部分场景,缺点是默认缓冲也比较小,不过这个可以调整,前提是你有管理员权限;
具体见http://blog.csdn.net/xiaofei0859/article/details/5868478
共享内存是最强大的,只是要做互斥
参考:
http://blog.csdn.net/21aspnet/article/details/7479469
http://blog.csdn.net/piaoairy219/article/details/17333691