一、進程通信的應用場景
- 數據傳輸:一個進程需要將它的數據發送給另一個進程,發送的數據量在一個字節到幾兆字節之間。
- 共享數據:多個進程想要操作共享數據,一個進程對共享數據的修改,別的進程應該立刻看到。
- 通知事件:一個進程需要向另一個或一組進程發送消息,通知它(它們)發生了某種事件(如進程終止時要通知父進程)。
- 資源共享:多個進程之間共享同樣的資源。為了作到這一點,需要內核提供鎖和同步機制。
- 進程控制:有些進程希望完全控制另一個進程的執行(如Debug進程),此時控制進程希望能夠攔截另一個進程的所有陷入和異常,並能夠及時知道它的狀態改變。
二、進程間的通信方式
- 管道(pipe),流管道(s_pipe)和有名管道(FIFO)
- 信號(signal)
- 消息隊列(message queue)
- 共享內存(shared memory)
- 信號量(sinal)
- 套接字(socket)
管道( pipe )
- 管道這樣的通訊方式有兩種限制,一是半雙工的通信,數據僅僅能單向流動,二是僅僅能在具有親緣關系的進程間使用。進程的親緣關系一般是指父子進程關系。
- 流管道s_pipe: 去除了第一種限制,能夠雙向傳輸.
- 有名管道:name_pipe克服了管道沒有名字的限制,因此,除具有管道所具有的功能外。它還同意無親緣關系進程間的通信;
信號量( semophore )
- 信號量是一個計數器,能夠用來控制多個進程對共享資源的訪問。
- 它常作為一種鎖機制。防止某進程正在訪問共享資源時。其它進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。
- 信號是比較復雜的通信方式,用於通知接受進程有某種事件發生,除了用於進程間通信外,進程還能夠發送信號給進程本身。linux除了支持Unix早期信號語義函數sigal外,還支持語義符合Posix.1標准的信號函數sigaction(實際上,該函數是基於BSD的,BSD為了實現可靠信號機制。又能夠統一對外接口,用sigaction函數又一次實現了signal函數);
消息隊列( message queue )
- 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。
- 消息隊列克服了信號傳遞信息少、管道僅僅能承載無格式字節流以及緩沖區大小受限等缺點。
- 消息隊列是消息的鏈接表。包含Posix消息隊列system V消息隊列。有足夠權限的進程能夠向隊列中加入消息,被賦予讀權限的進程則能夠讀走隊列中的消息。
- 消息隊列克服了信號承載信息量少,管道僅僅能承載無格式字節流以及緩沖區大小受限等缺點。
信號 ( singal )
- 信號是一種比較復雜的通信方式,用於通知接收進程某個事件已經發生。
- 主要作為進程間以及同一進程不同線程之間的同步手段。
共享內存( shared memory )
- 共享內存就是映射一段能被其它進程所訪問的內存。這段共享內存由一個進程創建。但多個進程都能夠訪問。共享內存是最快的 IPC 方式,
它是針對其它進程間通信方式執行效率低而專門設計的。 - 它往往與其它通信機制。如信號量,配合使用。來實現進程間的同步和通信。
套接字( socket )
- 套解口也是一種進程間通信機制,與其它通信機制不同的是。它可用於不同機器間的進程通信.
- 起初是由Unix系統的BSD分支開發出來的,但如今已作為一種通訊標准,與操作系統無關。
三、進程間通信各種方式效率比較
| 類型 | 無連接 | 可靠 | 流控制 | 記錄消息類型 | 優先級 |
|---|---|---|---|---|---|
| 普通PIPE | N | Y | Y | N | |
| 流PIPE | N | Y | Y | N | |
| 命名PIPE(FIFO) | N | Y | Y | N | |
| 消息隊列 | N | Y | Y | Y | |
| 信號量 | N | Y | Y | Y | |
| UNIX流socket | N | Y | Y | Y | |
| UNIX數據包socket | N | Y | Y | N |
注:無連接: 指無需調用某種形式的OPEN,就有發送消息的能力流控制:
假設系統資源短缺或者不能接收很多其它消息,則發送進程能進行流量控制.
各種通信方式的比較和優缺點
特點:
- 管道:速度慢。容量有限,僅僅有父子進程能通訊.
- FIFO:不論什么進程間都能通訊,但速度慢.
- 消息隊列:容量受到系統限制,且要注意第一次讀的時候,要考慮上一次沒有讀完數據的問題.
- 信號量:不能傳遞復雜消息,僅僅能用來同步.
- 共享內存區:能夠非常easy控制容量,速度快,但要保持同步,比方一個進程在寫的時候。還有一個進程要注意讀寫的問題,相當於線程中的線程安全。當然。共享內存區相同能夠用作線程間通訊,只是沒這個必要,線程間本來就已經共享了同一進程內的一塊內存.
分析:
-
假設用戶傳遞的信息較少或是須要通過信號來觸發某些行為.前文提到的軟中斷信號機制不失為一種簡捷有效的進程間通信方式.
-
但若是進程間要求傳遞的信息量比較大或者進程間存在交換數據的要求,那就須要考慮別的通信方式了。
-
無名管道簡單方便.但局限於單向通信的工作方式.而且僅僅能在創建它的進程及其子孫進程之間實現管道的共享:
-
有名管道盡管能夠提供給隨意關系的進程使用.可是因為其長期存在於系統之中。使用不當容易出錯.所以普通用戶一般不建議使用。
-
消息緩沖能夠不再局限於父子進程。而同意隨意進程通過共享消息隊列來實現進程間通信,並由系統調用函數來實現消息發送和接收之間的同步,從而使得用戶在使用消息緩沖進行通信時不再須要考慮同步問題,使用方便。可是信息的復制須要額外消耗CPU的時間,不適宜於信息量大或操作頻繁的場合。
-
共享內存針對消息緩沖的缺點改而利用內存緩沖區直接交換信息,無須復制。快捷、信息量大是其長處。可是共享內存的通信方式是通過將共享的內存緩沖區直接附加到進程的虛擬地址空間中來實現的,因此。這些進程之間的讀寫操作的同步問題操作系統無法實現。必須由各進程利用其它同步工具解決。另外,因為內存實體存在於計算機系統中。所以僅僅能由處於同一個計算機系統中的諸進程共享。
-
共享內存塊提供了在隨意數量的進程之間進行高效雙向通信的機制。每一個使用者都能夠讀取寫入數據。可是全部程序之間必須達成並遵守一定的協議,以防止諸如在讀取信息之前覆寫內存空間等競爭狀態的出現。不幸的是,Linux無法嚴格保證提供對共享內存塊的獨占訪問,甚至在通過使用
IPC_PRIVATE創建新的共享內存塊的時候也不能保證訪問的獨占性。同一時候,多個使用共享內存塊的進程之間必須協調使用同一個鍵值。
