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

進程間通訊概述


進程通訊的目的


  • 數據傳輸
    一個進程須要將它的數據發送給另外一個進程,發送的數據量在一個字節到幾M字節之間linux

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

  • 通知事
    一個進程須要向另外一個或一組進程發送消息,通知它(它們)發生了某種事件(如進程終止時要通知父進程)。網絡

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

  • 進程控制
    有些進程但願徹底控制另外一個進程的執行(如Debug進程),此時控制進程但願可以攔截另外一個進程的全部陷入和異常,並可以及時知道它的狀態改變。函數

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


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

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

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

Linux則把二者繼承了下來設計

  • 早期UNIX進程間通訊繼承

  • 基於System V進程間通訊

  • 基於Socket進程間通訊

  • POSIX進程間通訊。

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

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

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

因爲Unix版本的多樣性,電子電氣工程協會(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. 共享內存區:可以很容易控制容量,速度快,但要保持同步,好比一個進程在寫的時候,另外一個進程要注意讀寫的問題,至關於線程中的線程安全,固然,共享內存區一樣能夠用做線程間通信,不過沒這個必要,線程間原本就已經共享了同一進程內的一塊內存

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

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

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

有名管道雖然能夠提供給任意關係的進程使用.可是因爲其長期存在於系統之中,使用不當容易出錯.因此普通用戶通常不建議使用。

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

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

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

共享內存塊提供了在任意數量的進程之間進行高效雙向通訊的機制。每一個使用者均可以讀取寫入數據,可是全部程序之間必須達成並遵照必定的協議,以防止諸如在讀取信息以前覆寫內存空間等競爭狀態的出現。

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

相關文章
相關標籤/搜索