linux 進程間通訊(IPC)

1.管道:管道是Linux支持的最初Unix IPC形式之一,具備如下特色:linux

  • 管道是半雙工的,數據只能向一個方向流動;須要雙方通訊時,須要創建起兩個管道;
  • 只能用於父子進程或者兄弟進程之間(具備親緣關係的進程);
  • 單獨構成一種獨立的文件系統:管道對於管道兩端的進程而言,就是一個文件,但它不是普通的文件,它不屬於某種文件系統,而是自立門戶,單獨構成一種文件系統,而且只存在與內存中。
  • 數據的讀出和寫入:一個進程向管道中寫的內容被管道另外一端的進程讀出。寫入的內容每次都添加在管道緩衝區的末尾,而且每次都是從緩衝區的頭部讀出數據。

通常文件的I/O函數均可以用於管道,如close、read、write等等。web

從管道中讀取數據:函數

  • 若是管道的寫端不存在(或讀一個寫端已被關閉的管道時),在全部數據都被讀取後,則認爲已經讀到了數據的末尾,讀函數返回的讀出字節數爲0;(從技術方面考慮,管道的寫端還有進程時,就不會產生文件結束)
  • 當管道的寫端存在時,若是請求的字節數目大於PIPE_BUF,則返回管道中現有的數據字節數,若是請求的字節數目不大於PIPE_BUF,則返回管道中現有數據字節數(此時,管道中數據量小於請求的數據量);或者返回請求的字節數(此時,管道中數據量不小於請求的數據量)。注:(PIPE_BUF在include/linux/limits.h中定義,不一樣的內核版本可能會有所不一樣。Posix.1要求PIPE_BUF至少爲512字節,red hat 7.2中爲4096)。

向管道中寫入數據:spa

  • 向管道中寫入數據時,linux將不保證寫入的原子性,管道緩衝區一有空閒區域,寫進程就會試圖向管道寫入數據。若是讀進程不讀走管道緩衝區中的數據,那麼寫操做將一直阻塞。 
    注:只有在管道的讀端存在時,向管道中寫入數據纔有意義。不然,向管道中寫入數據的進程將收到內核傳來的SIFPIPE信號,應用程序能夠處理該信號,也能夠忽略(默認動做則是應用程序終止)。

管道可用於輸入輸出重定向,它將一個命令的輸出直接定向到另外一個命令的輸入。orm

管道的主要侷限性正體如今它的特色上:對象

  • 只支持單向數據流;
  • 只能用於具備親緣關係的進程之間;
  • 沒有名字;
  • 管道的緩衝區是有限的(管道制存在於內存中,在管道建立時,爲緩衝區分配一個頁面大小);
  • 管道所傳送的是無格式字節流,這就要求管道的讀出方和寫入方必須事先約定好數據的格式,好比多少字節算做一個消息(或命令、或記錄)等等;

2.FIFO:隊列

它能夠運行於多個非親屬關係間交換信息。進程

FIFO的打開規則:ip

若是當前打開操做是爲讀而打開FIFO時,若已經有相應進程爲寫而打開該FIFO,則當前打開操做將成功返回;不然,可能阻塞直到有相應進程爲寫而打開該FIFO(當前打開操做設置了阻塞標誌);或者,成功返回(當前打開操做沒有設置阻塞標誌)。內存

若是當前打開操做是爲寫而打開FIFO時,若是已經有相應進程爲讀而打開該FIFO,則當前打開操做將成功返回;不然,可能阻塞直到有相應進程爲讀而打開該FIFO(當前打開操做設置了阻塞標誌);或者,返回ENXIO錯誤(當前打開操做沒有設置阻塞標誌)。

從FIFO中讀取數據:

約定:若是一個進程爲了從FIFO中讀取數據而阻塞打開FIFO,那麼稱該進程內的讀操做爲設置了阻塞標誌的讀操做。

  • 若是有進程寫打開FIFO,且當前FIFO內沒有數據,則對於設置了阻塞標誌的讀操做來講,將一直阻塞。對於沒有設置阻塞標誌讀操做來講則返回-1,當前errno值爲EAGAIN,提醒之後再試。
  • 對於設置了阻塞標誌的讀操做說,形成阻塞的緣由有兩種:當前FIFO內有數據,但有其它進程在讀這些數據;另外就是FIFO內沒有數據。解阻塞的緣由則是FIFO中有新的數據寫入,不論信寫入數據量的大小,也不論讀操做請求多少數據量。
  • 讀打開的阻塞標誌只對本進程第一個讀操做施加做用,若是本進程內有多個讀操做序列,則在第一個讀操做被喚醒並完成讀操做後,其它將要執行的讀操做將再也不阻塞,即便在執行讀操做時,FIFO中沒有數據也同樣(此時,讀操做返回0)。
  • 若是沒有進程寫打開FIFO,則設置了阻塞標誌的讀操做會阻塞。

注:若是FIFO中有數據,則設置了阻塞標誌的讀操做不會由於FIFO中的字節數小於請求讀的字節數而阻塞,此時,讀操做會返回FIFO中現有的數據量。

向FIFO中寫入數據:

約定:若是一個進程爲了向FIFO中寫入數據而阻塞打開FIFO,那麼稱該進程內的寫操做爲設置了阻塞標誌的寫操做。

對於設置了阻塞標誌的寫操做:

  • 當要寫入的數據量不大於PIPE_BUF時,linux將保證寫入的原子性。若是此時管道空閒緩衝區不足以容納要寫入的字節數,則進入睡眠,直到當緩衝區中可以容納要寫入的字節數時,纔開始進行一次性寫操做。
  • 當要寫入的數據量大於PIPE_BUF時,linux將再也不保證寫入的原子性。FIFO緩衝區一有空閒區域,寫進程就會試圖向管道寫入數據,寫操做在寫完全部請求寫的數據後返回。

對於沒有設置阻塞標誌的寫操做:

  • 當要寫入的數據量大於PIPE_BUF時,linux將再也不保證寫入的原子性。在寫滿全部FIFO空閒緩衝區後,寫操做返回。
  • 當要寫入的數據量不大於PIPE_BUF時,linux將保證寫入的原子性。若是當前FIFO空閒緩衝區可以容納請求寫入的字節數,寫完後成功返回;若是當前FIFO空閒緩衝區不可以容納請求寫入的字節數,則返回EAGAIN錯誤,提醒之後再寫;

3.XSI  IPc結構

他們都屬於內核中的IPC結構, 它們都用標識符來描述. 這個標識符是一個非負整數, 與文件描述符不一樣的是, 建立時並不會重複利用經過刪除回收的整數, 而是每次+1, 直到整數最大值迴轉到0.

    標識符是IPC對象的內部名, 而它的外部名則是key(鍵), 它的基本類型是key_t, 在頭文件<sys/types.h>中定義爲長整型. 鍵由內核變換成標識符.

xsi ipc缺點:消息隊列和共享內存中的內容不會被自動刪除;不使用文件描述符,沒法使用多路轉接i/o函數:select和poll

優勢:可靠,流是受控的;能夠用非先進先出方式處理

(1)消息隊列

消息隊列最大的靈活性在於,咱們能夠本身定義傳遞給隊列的消息的數據類型,消息隊列比流通道稍耗內存

(2)共享內存

是一種最快的IPC

(3)信號量

在linux上,記錄縮與信號量相比,多耗事60%;可是想實現簡單功能,通常仍是用記錄所,由於其更簡單。

相關文章
相關標籤/搜索