http://blog.csdn.net/piaoairy219/article/details/17333691
1. 管道
管道的优点是不需要加锁。
缺点是默认缓冲区太小,只有4K。
一个管道只适合单向通信,如果要双向通信需要建立两个。
只适合父子进程间通信,而且不适合多个子进程,因为消息会乱。
它的发送接收机制是用read/write这种适用流的,缺点是数据本身没有边界,需要应用程序自己解释,而一般消息大多是一个固定长的消息头,和一个变长的消息体,一个子进程从管道read到消息头后,消息体可能被别的子进程接收到。
2. 消息队列
消息队列也不需要加锁。
默认缓冲区和单消息上限都要大一些,在我的suse10上是64K。
它并不局限于父子进程间通信,只要一个相同的key,就可以让不同的进程定位到同一个消息队列上。它也可以用来双向通信,只要稍微加个标识,可以通过消息中的type进行区分,比如一个任务分派进程,创建了若干个执行子进程,不管是父进程发送分派任务的消息,还是子进程发送任务执行的消息,都将type设置为目标进程的pid,因为msgrcv可以指定只接收消息类型为type的消息,这样就实现了子进程只接收自己的任务,父进程只接收任务结果。
3. 共享内存
共享内存几乎可以认为没有上限。
它也是不局限于父子进程,采用与消息队列类似的定位方式,因为内存是共享的,不存在任何单向的限制。
最大的问题就是需要应用程序自己做互斥,有如下几种方案:
(1)只适用于两个进程共享。在内存中放一个标志位,一定要声明为volatile,大家基于标志位来互斥,例如为0时第一个可以写,第二个就等待,为1时第一个等待,第二个可以写/读。
(2)也只适用于两个进程。是用信号,大家等待不同的信号,第一个写完了发送信号2,等待信号1,第二个等待信号2,收到后读取/写入完,发送信号1。它不适用于更多进程是因为虽然父进程可以向不同子进程分别发送信号,但是子进程收到信号会同时访问共享内存,产生不同子进程间的竞态条件。如果用多块共享内存,又存在子进程发送结果通知信号时,父进程收到信号后,不知道是谁发送,也意味着不知道该访问哪块共享内存。即使子进程发送不同的结果通知信号,因为等待信号的一定是阻塞的,如果某个子进程意外终止,父进程将永远阻塞下去,而不能超时处理。
(3)采用信号量或者msgctl自己的加锁、解锁功能,不过后者只适用于linux。
总结
管道是最弱的,只适合有限的场景。
消息队列能适合大部分场景,缺点是默认缓冲区也比较小,不过这个可以调整,前提是你有管理员权限。
共享内存是最强大的,只是要做互斥。