1. 程式人生 > >linux 進程間通信的3種高級方式及優缺點

linux 進程間通信的3種高級方式及優缺點

linux 存在 發現 行數據 移植 ipc 網絡 程序 linux 進程

由於不同的進程運行在各自不同的內存空間中.一方對於變量的修改另一方是無法感知的.因此.進程之間的信息傳遞不可能通過變量或其它數據結構直接進行,只能通進程間通信來完成。

根據進程通信時信息量大小的不同,可以將進程通信劃分為兩大類型:控制信息的通信和大批數據信息的通信.前者稱為低級通信,後者稱為高級通信。

低級通信主要用於進程之間的同步、互斥、終止、掛起等等控制信息的傳遞。

高級通信主要用於進程間數據塊的交換和共享 常見的高級通信有管道(PIPE)、消息隊列(MESSAGE)、共享內存(SHARED MEM0RY)等。

這裏主要比較一下高級通信的這三種方式的特點。

管道通信(PIPE)
兩個進程利用管道進行通信時.發送信息的進程稱為寫進程.接收信息的進程稱為讀進程。管道通信方式的中間介質就是文件.通常稱這種文件為管道文件.它就像管道一樣將一個寫進程和一個讀進程連接在一起,實現兩個進程之間的通信。寫進程通過寫入端(發送端)往管道文件中寫入信息;讀進程通過讀出端(接收端)從管道文件中讀取信息。兩個進程協調不斷地進行寫和讀,便會構成雙方通過管道傳遞信息的流水線。
利用系統調用PIPE()可以創建一個無名管道文件,通常稱為無名管道或PIPE;利用系統調用MKNOD()可以創建一個有名管道文件.通常稱為有名管道或FIFO。無名管道是一種非永
久性的管道通信機構.當它訪問的進程全部終止時,它也將隨之被撤消。無名管道只能用在具有家族聯系的進程之間。有名管道可以長期存在於系統之中.而且提供給任意關系的進程使用,但是使用不當容易導致出錯.所以操作系統將命名管道的管理權交由系統來加以控制管道文件被創建後,可以通過系統調用WRITE()和READ()來實現對管道的讀寫操作;通信完後,可用CLOSE()將管道文件關閉。

消息緩沖通信(MESSAGE)
多個獨立的進程之間可以通過消息緩沖機制來相互通信.這種通信的實現是以消息緩沖區為中間介質.通信雙方的發送和接收操作均以消息為單位。在存儲器中,消息緩沖區被組織成隊列,通常稱之為消息隊列。消息隊列一旦創建後即可由多進程共享.發送消息的進程可以在任意時刻發送任意個消息到指定的消息隊列上,並檢查是否有接收進程在等待它所發送的消息。若有則喚醒它:而接收消息的進程可以在需要消息的時候到指定的消息隊列上獲取消息.如果消息還沒有到來.則轉入睡眠狀態等待。

共享內存通信(SHARED MEMORY)
針對消息緩沖需要占用CPU進行消息復制的缺點.OS提供了一種進程間直接進行數據交換的通信方式一共享內存 顧名思義.這種通信方式允許多個進程在外部通信協議或同步,互斥機制的支持下使用同一個內存段(作為中間介質)進行通信.它是一種最有效的數據通信方式,其特點是沒有中間環節.直接將共享的內存頁面通過附接.映射到相互通信的進程各自的虛擬地址空間中.從而使多個進程可以直接訪問同一個物理內存頁面.如同訪問自己的私有空間一樣(但實質上不是私有的而是共享的)。因此這種進程間通信方式是在同一個計算機系統中的諸進程間實現通信的最快捷的方法.而它的局限性也在於此.即共享內存的諸進程必須共處同一個計算機系統.有物理內存可以共享才行。

三種方式的特點(優缺點):

1.無名管道簡單方便.但局限於單向通信的工作方式.並且只能在創建它的進程及其子孫進程之間實現管道的共享:有名管道雖然可以提供給任意關系的進程使用.但是由於其長期存在於系統之中,使用不當容易出錯。

2.消息緩沖可以不再局限於父子進程.而允許任意進程通過共享消息隊列來實現進程間通信.並由系統調用函數來實現消息發送和接收之間的同步.從而使得用戶在使用消息緩沖進行通信時不再需要考慮同步問題.使用方便,但是信息的復制需要額外消耗CPU的時間.不適宜於信息量大或操作頻繁的場合。

3.共享內存針對消息緩沖的缺點改而利用內存緩沖區直接交換信息,無須復制,快捷、信息量大是其優點。但是共享內存的通信方式是通過將共享的內存緩沖區直接附加到進程的虛擬地址空間中來實現的.因此,這些進程之間的讀寫操作的同步問題操作系統無法實現。必須由各進程利用其他同步工具解決。另外,由於內存實體存在於計算機系統中.所以只能由處於同一個計算機系統中的諸進程共享。不方便網絡通信。

補充:

1.

# 管道( pipe ):管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關系的進程間使用。進程的親緣關系通常是指父子進程關系。

# 有名管道 (named pipe) : 有名管道也是半雙工的通信方式,但是它允許無親緣關系進程間的通信。

# 信號量( semophore ) : 信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。

# 消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩沖區大小受限等缺點。

# 信號 ( sinal ) : 信號是一種比較復雜的通信方式,用於通知接收進程某個事件已經發生。

#共享內存( shared memory):共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的IPC方式,它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號量,配合使用,來實現進程間的同步和通信。# 套接字( socket ) : 套解口也是一種進程間通信機制,與其他通信機制不同的是,它可用於不同及其間的進程通信。

管道的主要局限性正體現在它的特點上:
只支持單向數據流;
只能用於具有親緣關系的進程之間;
沒有名字;
管道的緩沖區是有限的(管道制存在於內存中,在管道創建時,為緩沖區分配一個頁面大小);
管道所傳送的是無格式字節流,這就要求管道的讀出方和寫入方必須事先約定好數據的格式,比如多少字節算作一個消息(或命令、或記錄)等等;

2.

用於進程間通訊(IPC)的四種不同技術:
1. 消息傳遞(管道,FIFO,posix和system v消息隊列)
2. 同步(互斥鎖,條件變量,讀寫鎖,文件和記錄鎖,Posix和System V信號燈)
3. 共享內存區(匿名共享內存區,有名Posix共享內存區,有名System V共享內存區)
4. 過程調用(Solaris門,Sun RPC)
消息隊列和過程調用往往單獨使用,也就是說它們通常提供了自己的同步機制.相反,共享內存區通常需要由應用程序提供的某種同步形式才能正常工作.解決某個特定問題應使用哪種IPC不存在簡單的判定,應該逐漸熟悉各種IPC形式提供的機制,然後根據特定應用的要求比較它們的特性.

必須考慮的四個前提:
1. 聯網的還是非聯網的.IPC適用於單臺主機上的進程或線程間的.如果應用程序有可能分布到多臺主機上,那就要考慮使用套接字代替IPC,從而簡化以後向聯網的應用程序轉移的工作.
2. 可移植性.
3. 性能,在具體的開發環境下運行測試程序,比較幾種IPC的性能差異.
4. 實時調度.如果需要這一特性,而且所用的系統也支持posix實時調度選項,那就考慮使用Posix的消息傳遞和同步函數.

各種IPC之間的一些主要差異:
1. 管道和FIFO是字節流,沒有消息邊界.Posix消息和System V消息則有從發送者向接受者維護的記錄邊界(eg:TCP是沒有記錄邊界的字節流,UDP則提供具有記錄邊界的消息).
2. 當有一個消息放置到一個空隊列中時,Posix消息隊列可向一個進程發送一個信號,或者啟動一個新的線程.System V則不提供類似的通知形式.
3. 管道和FIFO的數據字節是先進先出的.Posix消息和System V消息具有由發送者賦予的優先級.從一個Posix消息隊列讀出時,首先返回的總是優先級最高的消息.從一個System V消息隊列讀出時,讀出者可以要求想要的任意優先級的消息.
4. 在眾多的消息傳遞技術—管道,FIFO,Posix消息隊列和System V消息隊列—中,可從一個信號處理程序中調用的函數只有read和write(適用於管道和FIFO).

比較不同形式的消息傳遞時,我們感興趣的有兩種測量尺度:
1.帶寬(bandwidth):數據通過IPC通道轉移的速度.為測量該值,我們從一個進程向另一個進程發送大量數據(幾百萬字節).我們還給不同大小的I/O操作(例如管道和FIFO的write和read操作)測量該值,期待發現帶寬隨每個I/O操作的數據量的增長而增長的規律.
2. 延遲(latency):一個小的IPC消息從一個進程到令一個進程再返回來所花的時間.我們測量的是只有一個1個字節的消息從一個進程到令一個進程再回來的時間(往返時間)

在現實世界中,帶寬告訴我們大塊數據通過一個IPC通道發送出去需花多長時間,然而IPC也用於傳遞小的控制信息,系統處理這些小消息所需的時間就由延遲提供.這兩個數都很重要.

linux 進程間通信的3種高級方式及優缺點