進程間通訊IPC的幾種方式的優缺點總結

Linux進程間的通訊

Unix發展做出重大貢獻的兩大主力AT&T的貝爾實驗室及BSD(加州大學伯克利分校的伯克利軟件發佈中心)在進程間通信方面的側重點有所不同。前者對Unix早期的進程間通信手段進行了系統的改進和擴充,形成了“system V IPC”,通信進程侷限在單個計算機內;後者則跳過了該限制,形成了基於套接口(socket)的進程間通信機制。Linux則把兩者繼承了下來,如圖示:

                                                

管道

管道的通信介質是文件,這種文件通常稱爲管道文件,兩個進程利用管道文件進行通信時,一個進程爲寫進程,另一個進程爲讀進程。寫進程通過寫端(發送端)往管道文件中寫入信息;讀進程通過讀端(接收端)從管道文件中讀取信息。兩個進程協調不斷地進行寫、讀,便會構成雙方通過管道傳遞信息的流水線。

匿名管道pipe

匿名管道是半雙工的,數據只能單向通信;需要雙方通信時,需要建立起兩個管道;只能用於父子進程或者兄弟進程之間(具有親緣關係的進程)。

命名管道fifo

不同於匿名管道之處在於它提供一個路徑名與之關聯,以FIFO的文件形式存在於文件系統中。這樣,即使與FIFO的創建進程不存在親緣關係的進程,只要可以訪問該路徑,就能夠彼此通過FIFO相互通信(能夠訪問該路徑的進程以及FIFO的創建進程之間),因此,通過FIFO不相關的進程也能交換數據。值得注意的是,FIFO嚴格遵循先進先出(first in first out),對管道及FIFO的讀總是從開始處返回數據,對它們的寫則把數據添加到末尾。

信號

信號是一種比較複雜的通信方式,信號產生的條件:按鍵、硬件異常、進程調用kill函數將信號發送給另一個進程、用戶調用kill命令將信號發送給其他進程,信號傳遞的消息比較少,主要用於通知接收進程某個時間已經發生。

消息隊列

消息隊列是消息的鏈表,存放在內核中並由消息隊列標識符標識,消息隊列克服了信號傳遞信息少,管道只能承載無格式字節流以及緩衝區大小受限等特點。消息隊列起信箱作用,到了就掛在那裏,需要的時候去取。消息隊列提供了一種在兩個不相關進程間傳遞數據的簡單有效的方法。與命名管道相比:消息隊列的優勢在於,它獨立於發送和接收進程而存在,這消除了在同步命名管道的打開和關閉時可能產生的一些困難。消息隊列提供了一種從一個進程向另一個進程發送一個數據塊的方法。而且,每個數據塊被認爲含有一個類型,接收進程可以獨立地接收含有不同類型值的數據塊。

優點:

      A. 我們可以通過發送消息來幾乎完全避免命名管道的同步和阻塞問題。

      B. 我們可以用一些方法來提前查看緊急消息。

缺點:

      A. 與管道一樣,每個數據塊有一個最大長度的限制。

      B. 系統中所有隊列所包含的全部數據塊的總長度也有一個上限。

Linux系統中有兩個宏定義:

MSGMAX, 以字節爲單位,定義了一條消息的最大長度。

MSGMNB, 以字節爲單位,定義了一個隊列的最大長度。

共享內存

共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的IPC方式,它是針對其他進程間通信方式運行效率低而專門設計的。訪問共享內存區域和訪問進程獨有的內存區域一樣快,並不需要通過系統調用或者其它需要切入內核的過程來完成。同時它也避免了對數據的各種不必要的複製。共享內存塊提供了在任意數量的進程之間進行高效雙向通信的機制。每個使用者都可以讀取寫入數據,往往與其他通信機制,如信號量配合使用,來實現進程間的同步和通信。而它的侷限性也在於此.即共享內存的諸進程必須共處同一個計算機系統.有物理內存可以共享纔行。共享在共享大數據文件時有用,直接在相同進行內存的拷貝,速度快,效率高,需要考慮訪問臨界資源併發同步。共享內存區是最快的可用IPC形式,一旦這樣的內存區映射到共享它的進程的地址空間,這些進程間數據的傳遞就不再通過執行任何進入內核的系統調用來傳遞彼此的數據,節省了時間。

共享內存和消息隊列,FIFO,管道傳遞消息的區別:

消息隊列,FIFO,管道的消息傳遞方式一般爲

1:服務器得到輸入

2:通過管道,消息隊列寫入數據,通常需要從進程拷貝到內核。

3:客戶從內核拷貝到進程

4:然後再從進程中拷貝到輸出文件

上述過程通常要經過4次拷貝,才能完成文件的傳遞。

共享內存只需要

1:從輸入文件到共享內存區

2:從共享內存區輸出到文件

上述過程不涉及到內核的拷貝,所以花的時間較少。

本地套接字

進程間通信的一種方式是使用UNIX套接字sockaddr_un,人們在使用這種方式時往往用的不是網絡套接字,而是一種稱爲本地套接字的方式。本地套接字用於本地進程間的通訊更安全和穩定。

使用套接字函數socket創建,不過傳遞的參數與網絡套接字不同。域參數應該是PF_LOCAL或者PF_UNIX,而不能用PF_INET之類。本地套接字的通訊類型應該是SOCK_STREAM或SOCK_DGRAM,協議爲默認協議。

創建了套接字後,還必須進行綁定才能使用。不同於網絡套接字的綁定,本地套接字的綁定的是struct sockaddr_un結構。struct sockaddr_un結構有兩個參數:sun_family、sun_path。sun_family只能是AF_LOCAL或AF_UNIX,而sun_path是本地文件的路徑。通常將文件放在/tmp目錄下。

本地套接字的其他操作都與網絡套接字相似。

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