管道、消息队列、共享内存对比
匿名管道:
1.优点 不需要加锁
2.缺点 默认缓冲区太小,只有4k
3.进程父子间通信
4.单向通信,半双工,通信时需要关闭不需要的读写
5.是一种非永久性的管道通信机构,当它访问的进程全部终止时,它也将随之被撤消
命名管道(一个文件)
1.优点 不需要加锁
2.缺点 默认缓冲区太小,只有4k
3.可以多进程通信
4.单向通信
5.而FIFO是一种永久的管道通信机构。通信完毕后,可使用close()将管道文件关闭。命名管道的文件是硬盘上的设备文件,是可见的。
6.不同于匿名管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信。
消息队列
- 不需要加锁
- 默认缓冲区和单消息上限都要大一些
- 不局限于父子进程间通信
- 也可以双向通信不过稍微加个标识,可以通过消息中的type进行区分,比如一个任务分派进程,创建了若干个执行子进程,不管是父进程发送分派任务的消息,还是子进程发送任务执行的消息,都将type设置为目标进程的pid,因为msgrcv可以指定只接收消息类型为type的消息,这样就实现了子进程只接收自己的任务,父进程只接收任务结果
- 只需要相同的key,就可以让不同进程定位到同一消息队列上
6.与命名管道相比:消息队列的优势在于,它独立于发送和接收进程而存在,这消除了在同步命名管道的打开和关闭时可能产生的一些困难。消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。而且,每个数据块被认为含有一个类型,接收进程可以独立地接收含有不同类型值的数据块。
7.优点:
我们可以通过发送消息来几乎完全避免命名管道的同步和阻塞问题。
我们可以用一些方法来提前查看紧急消息。
缺点:
与管道一样,每个数据块有一个最大长度的限制。
系统中所有队列所包含的全部数据块的总长度也有一个上限。
8.Linux系统中有两个宏定义:
MSGMAX, 以字节为单位,定义了一条消息的最大长度。
MSGMNB, 以字节为单位,定义了一个队列的最大长度。
共享内存
1.
- 没有上限
- 不局限于父子进程,采用跟消息队列类似的定位方式
- 不存在任何单向的限制
需要应用程序自己做互斥( 若一个进程正在向共享内存区写数据,则在它做完这一步操作前,别的进程不应当去读、写这些数据。)有如下三种互斥方案
1 只适用两个进程共享,在内存中放一个标志位,一定要声明为volatile,大家基于标志位来互斥,例如为0时第一个可以写,第二个就等待,为1时第一个等待,第二个可以写/读
2 也只适用两个进程,是用信号。
3 采用信号量或者msgctl自己的加锁、解锁功能,不过后者只适用于linux
5.共享内存和消息队列,FIFO,管道传递消息的区别:
消息队列,FIFO,管道的消息传递方式一般为
1:服务器得到输入
2:通过管道,消息队列写入数据,通常需要从进程拷贝到内核。
3:客户从内核拷贝到进程
4:然后再从进程中拷贝到输出文件
上述过程通常要经过4次拷贝,才能完成文件的传递。
共享内存只需要
1:从输入文件到共享内存区
2:从共享内存区输出到文件
上述过程不涉及到内核的拷贝,所以花的时间较少。
参考https://blog.youkuaiyun.com/ttyue_123/article/details/52370676
https://blog.youkuaiyun.com/piaoairy219/article/details/17333691