Linux進程間通訊的幾種方式總結--linux內核剖析(七)

進程間通訊概述


進程通訊的目的


  • 傳輸數據
    一個進程需要將它的數據發送給還有一個進程。發送的數據量在一個字節到幾M字節之間linux

  • 共享數據
    多個進程想要操做共享數據,一個進程對共享數據安全

  • 通知事
    一個進程需要向還有一個或一組進程發送消息。通知它(它們)發生了某種事件(如進程終止時要通知父進程)。markdown

  • 資源共享
    多個進程之間共享相同的資源。爲了做到這一點,需要內核提供鎖和同步機制。網絡

  • 進程控制
    有些進程但願全然控制還有一個進程的執行(如Debug進程),此時控制進程但願可以攔截還有一個進程的所有陷入和異常,並可以及時知道它的狀態改變。socket

Linux 進程間通訊(IPC)的發展


linux下的進程通訊手段基本上是從Unix平臺上的進程通訊手段繼承而來的。而對Unix發展作出重大貢獻的兩大主力AT&T的貝爾實驗室及BSD(加州大學伯克利分校的伯克利軟件公佈中心)在進程間通訊方面的側重點有所不一樣。函數

前者對Unix早期的進程間通訊手段進行了系統的改進和擴充,造成了「system V IPC」。通訊進程侷限在單個計算機內;工具

後者則跳過了該限制,造成了基於套接口(socket)的進程間通訊機制。post

Linux則把二者繼承了下來操作系統

  • 早期UNIX進程間通訊線程

  • 基於System V進程間通訊

  • 基於Socket進程間通訊

  • POSIX進程間通訊。

UNIX進程間通訊方式包含:管道、FIFO、信號。

System V進程間通訊方式包含:System V消息隊列、System V信號燈、System V共享內存

POSIX進程間通訊包含:posix消息隊列、posix信號燈、posix共享內存。

由於Unix版本號的多樣性,電子電氣project協會(IEEE)開發了一個獨立的Unix標準,這個新的ANSI Unix標準被稱爲計算機環境的可移植性操做系統界面(PSOIX)。

現有大部分Unix和流行版本號都是遵循POSIX標準的。而Linux從一開始就遵循POSIX標準;

BSD並不是沒有涉足單機內的進程間通訊(socket自己就可以用於單機內的進程間通訊)。

其實,很是多Unix版本號的單機IPC留有BSD的痕跡。如4.4BSD支持的匿名內存映射、4.3+BSD對可靠信號語義的實現等等。

linux使用的進程間通訊方式


  1. 管道(pipe),流管道(s_pipe)和有名管道(FIFO)

  2. 信號(signal)

  3. 消息隊列

  4. 共享內存

  5. 信號量

  6. 套接字(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 方式,它是針對其它進程間通訊方式執行效率低而專門設計的。

它每每與其它通訊機制。如信號量,配合使用。來實現進程間的同步和通訊。

使得多個進程可以訪問同一塊內存空間。是最快的可用IPC形式。

是針對其它通訊機制執行效率較低而設計的。每每與其它通訊機制,如信號量結合使用。來達到進程間的同步及相互排斥。

套接字( socket )


套解口也是一種進程間通訊機制,與其它通訊機制不一樣的是。它可用於不一樣機器間的進程通訊

更爲通常的進程間通訊機制。可用於不一樣機器之間的進程間通訊。

起初是由Unix系統的BSD分支開發出來的,但現在通常可以移植到其它類Unix系統上:Linux和System V的變種都支持套接字。

進程間通訊各類方式效率比較


類型 無鏈接 可靠 流控制 記錄消息類型 優先級
普通PIPE N Y Y N
流PIPE N Y Y N
命名PIPE(FIFO) N Y Y N
消息隊列 N Y Y Y
信號量 N Y Y Y
共享存儲 N Y Y Y
UNIX流SOCKET N Y Y N
UNIX數據包SOCKET Y Y N N

注:無鏈接: 指無需調用某種形式的OPEN,就有發送消息的能力流控制:

假設系統資源短缺或者不能接收不少其它消息,則發送進程能進行流量控制

各類通訊方式的比較和優缺點

  1. 管道:速度慢。容量有限,僅僅有父子進程能通信

  2. FIFO:不論什麼進程間都能通信,但速度慢

  3. 消息隊列:容量受到系統限制,且要注意第一次讀的時候,要考慮上一次沒有讀完數據的問題

  4. 信號量:不能傳遞複雜消息,僅僅能用來同步

  5. 共享內存區:可以很是easy控制容量,速度快,但要保持同步,比方一個進程在寫的時候。還有一個進程要注意讀寫的問題,至關於線程中的線程安全。固然。共享內存區相同可以用做線程間通信,只是沒這個必要,線程間原本就已經共享了同一進程內的一塊內存

假設用戶傳遞的信息較少或是需要經過信號來觸發某些行爲.前文提到的軟中斷信號機制不失爲一種簡捷有效的進程間通訊方式.

但如果進程間要求傳遞的信息量比較大或者進程間存在交換數據的要求,那就需要考慮別的通訊方式了。

無名管道簡單方便.但侷限於單向通訊的工做方式.並且僅僅能在建立它的進程及其子孫進程之間實現管道的共享:

有名管道盡管可以提供給隨意關係的進程使用.但是由於其長期存在於系統之中。使用不當easy出錯.因此普通用戶通常不建議使用。

消息緩衝可以再也不侷限於父子進程。而贊成隨意進程經過共享消息隊列來實現進程間通訊,並由系統調用函數來實現消息發送和接收之間的同步,從而使得用戶在使用消息緩衝進行通訊時再也不需要考慮同步問題,使用方便。但是信息的複製需要額外消耗CPU的時間,不適宜於信息量大或操做頻繁的場合。

共享內存針對消息緩衝的缺點改而利用內存緩衝區直接交換信息,無須複製。快捷、信息量大是其長處。

但是共享內存的通訊方式是經過將共享的內存緩衝區直接附加到進程的虛擬地址空間中來實現的,所以。這些進程之間的讀寫操做的同步問題操做系統沒法實現。必須由各進程利用其它同步工具解決。另外,由於內存實體存在於計算機系統中。因此僅僅能由處於同一個計算機系統中的諸進程共享。

不方便網絡通訊。

共享內存塊提供了在隨意數量的進程之間進行高效雙向通訊的機制。

每個使用者都可以讀取寫入數據。但是所有程序之間必須達成並遵照必定的協議,以防止諸如在讀取信息以前覆寫內存空間等競爭狀態的出現。

不幸的是,Linux沒法嚴格保證提供對共享內存塊的獨佔訪問,甚至是在您經過使用IPC_PRIVATE建立新的共享內存塊的時候也不能保證訪問的獨佔性。 同一時候,多個使用共享內存塊的進程之間必須協調使用同一個鍵值。

相關文章
相關標籤/搜索