管道概念
匿名管道PIPE
匿名管道的特點
常見問題
命名管道
命名管道特點:
管道概念
管道是一種虛拟檔案,它可以連接配接兩個程序,如果程序A和B希望通過管道進行通信,當程序A想對B發送資料時,他把資料寫到管道上,仿佛管道就是輸出檔案一樣,程序B可以通過該管道讀取到A寫入的資料,仿佛管道就是輸入檔案一樣。
這樣UNIX中, 兩個程序之間的通信就類似于普通檔案的讀寫,更為強大的是如果程序發現它所寫入的輸出檔案不是真正的檔案而是管道,則需要使用特殊的系統調用
匿名管道PIPE
匿名管道是用于有親緣關系的程序間通信的,即fork建立出的子程序。
#include <unistd.h>
int pipe(int filed[2]);
函數功能:調用pipe函數時在核心中開辟出一塊緩沖區(稱為管道)用于通信,參數為輸出型參數,傳回值為傳出的兩個檔案描述符,其中filed[0]指向管道的讀端,filed[1]指向管道的寫端(其中0相當于标準輸入,1相當于标準輸出),是以管道在使用者程式看起來就像一個打開的檔案。調用成功傳回0,調用失敗傳回-1。關閉管道,僅需将兩個檔案描述符關閉即可。
注: 用 pipe() 建立的管道兩端處于同一個程序中,由于管道主要是用于在不同的程序間通信的,是以,在實際應用中沒有太大意義。實際上,fork()必須在pipe()之前來建立子程序,否則子程序無法程序相應的檔案描述符,,該子程序會繼承父程序所建立的管道,這時,父子程序管道的檔案描述符對應關系如下圖
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL5kTM1MjMzUTM4ATNwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
匿名管道的特點
(1)隻能進行單向通信,具有固定的讀端和寫端;若要實作雙向通信必須建立兩個管道。
(2)隻能用于具有血緣關系的程序,常用于父子程序之間;
(3)生命周期:随程序(因為管道的本質是檔案,程序結束時檔案就會關閉)
(4)管道是基于位元組流的;
(5)管道内部實作同步機制,實作了資料一緻性;核心會對管道操作進行同步與互斥
常見問題
(1)有指向管道寫端的檔案描述符沒有關閉,也沒有向管道中寫資料,這時有程序從管道中讀資料,那麼管道中的剩餘資料被讀取完之後會進入阻塞,直到管道中有資料可讀時才讀取資料并傳回
(2)指向管道讀端的檔案描述符沒有關閉,也沒有從管道中讀取資料,但是有程序向管道中寫資料,在管道被寫滿時,在寫時write會阻塞,直到管道中再次有空位置才寫入資料并傳回。
(3)指向寫端的程序一直在寫,但是指向讀端的檔案描述符都關閉了,這時該程序會收到信号SIGPIPE,導緻程序異常終止。
(4)所有指向管道寫端的檔案描述符都關閉了,讀程序依然在不停的讀資料,當管道中剩餘的資料被讀完時,就會傳回0,相當于讀到檔案結束符。
是以要設計同步機制,合适的時候讀,合适的時候寫
命名管道
命名管道相較于匿名管道的不同,就是能夠适用于任意程序間的通信。不同的是,匿名管道在用pipe函數建立的同時也打開了,而命名管道在mkfifo建立了之後,還需用open函數打開該命名管道。打開的時候模式可以選擇阻塞和非阻塞等模式。
#include <unistd.h>
int mkfifo(const char* pathname,mode_t mode)
命名管道特點:
(1)隻能進行單向通信,允許任何兩個不相關程序之間進行互相通信;
(2)該管道可以通過路徑名來指出,并且在檔案系統中是可見的。在建立了管道之後,兩個程序就可以把它當做普通檔案一樣進行讀寫操作,使用非常友善;
(3) FIFO嚴格地遵循先進先出規則,對管道及FIFO的讀總是從開始處傳回資料,對它們的寫則是把資料添加到末尾,它們不支援如 lseek()等檔案定位操作。