消息队列和管道的区别以及和共享内存相比效率低的原因

来源:互联网 发布:南方网络笑星 编辑:程序博客网 时间:2024/04/28 02:47

管道和消息队列的区别


管道(PIPE)

管道通信方式的中间介质是文件,通常称这种文件为管道文件。两个进程利用管道文件进行通信时,一个

进程为写进程,另一个进程为读进程。写进程通过写端(发送端)往管道文件中写入信息;读进程通过读

端(接收端)从管道文件中读取信息。两个进程协调不断地进行写、读,便会构成双方通过管道传递信息

的流水线。

管道分为匿名管道和命名管道。

匿名管道:管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)。

命名管道可在同一台计算机的不同进程之间或在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数据通信

不同于匿名管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,通过FIFO不相关的进程也能交换数据。值得注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。

利用系统调用PIPE()创建一个无名管道文件,通常称为无名管道或PIPE;利用系统调用MKNOD()创建

一个有名管道文件,通常称为有名管道或FIFO。

PIPE是一种非永久性的管道通信机构,当它访问的进程全部终止时,它也将随之被撤消;它也不能用于不

同族系的进程之间的通信。而FIFO是一种永久的管道通信机构,它可以弥补PIPE的不足。

管道文件被创建后,便可对它进行读写操作,通过系统调用WRITE()和READ()来实现。通信完毕后,

可将管道文件关闭,用CLOSE()来实现。

消息队列(message queue)

消息队列也是System V IPC机制之一。
消息队列与命名管道类似,
但少了打开和关闭管道方面的复杂性。
但使用消息队列并未解决我们在使用命名管道时遇到的一些问题,
如管道满时的阻塞问题。

消息队列提供了一种在两个不相关进程间传递数据的简单有效的方法。
与命名管道相比:
消息队列的优势在于,它独立于发送和接收进程而存在,
这消除了在同步命名管道的打开和关闭时可能产生的一些困难。

消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。
而且,每个数据块被认为含有一个类型,
接收进程可以独立地接收含有不同类型值的数据块。

好消息是:
A. 我们可以通过发送消息来几乎完全避免命名管道的同步和阻塞问题。
而且,
B. 我们可以用一些方法来提前查看紧急消息。

坏消息是:
A. 与管道一样,每个数据块有一个最大长度的限制,
而且,
B. 系统中所有队列所包含的全部数据块的总长度也有一个上限。

Linux系统中有两个宏定义:
 MSGMAX, 以字节为单位,定义了一条消息的最大长度。
 MSGMNB, 以字节为单位,定义了一个队列的最大长度。

========================

共享内存比管道和消息队列效率高的原因

共享内存区是最快的可用IPC形式,一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据的传递就不再通过执行任何进入内核的系统调用来传递彼此的数据,节省了时间。
    共享内存和消息队列,FIFO,管道传递消息的区别:
    后者,消息队列,FIFO,管道的消息传递方式一般为
    1:服务器得到输入
    2:通过管道,消息队列写入数据,通常需要从进程拷贝到内核。
    3:客户从内核拷贝到进程
    4:然后再从进程中拷贝到输出文件
    上述过程通常要经过4次拷贝,才能完成文件的传递。
    而共享内存只需要
    1:从输入文件到共享内存区
    2:从共享内存区输出到文件
    上述过程不涉及到内核的拷贝,所以花的时间较少。

1 0