消息隊列和管道的區別以及和共享內存相比效率低的原因

管道和消息隊列的區別


管道(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:從共享內存區輸出到文件
    上述過程不涉及到內核的拷貝,所以花的時間較少。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章