51 無名管道

2021-10-14 16:37:57 字數 2450 閱讀 4120

這恐怕是最古老的 linux 程序間通訊的方式了。這種方式簡單而又強大,尤其適合有親緣關係的程序(通常是父子程序)間通訊了。

實際上,你或多或少的都用過管道這種通訊方式,比如你在使用的 linux 命令中的管道連線符|。所以,對於管道來說,你應該有一種親切感。

如果你實踐過前面我們講過的使用本地檔案進行程序間通訊的方式,那麼你就可以把管道理解成位於程序核心空間(如果你不記得這個概念,請翻閱前面的博文)的「檔案」。

圖1 假想的位於核心的管道檔案

給檔案加引號,是因為它和檔案確實很像,因為它也有描述符。但是它確實又不是普通的本地檔案,而是一種抽象的存在。

當程序使用pipe函式,就可以開啟位於核心中的這個特殊「檔案」。同時pipe函式會返回兩個描述符,乙個用於讀,乙個用於寫。如果你使用fstat函式來測試該描述符,可以發現此檔案型別為 fifo.

而無名管道的無名,指的就是這個虛幻的「檔案」,它沒有名字。

本質上,pipe 函式會在程序核心空間申請一塊記憶體(比如乙個記憶體頁,一般是 4kb),然後把這塊記憶體當成乙個先進先出(fifo)的迴圈佇列來訪問資料,這一切都由作業系統幫助我們實現了。

int

pipe(int pipefd[2]);

pipe 函式開啟的檔案描述符是通過引數(陣列)傳遞出來的,而返回值表示開啟成功(0)或失敗(-1)。

它的引數是乙個大小為 2 的陣列。此陣列的第 0 個元素用來接收以的方式開啟的描述符,而第 1 個元素用來接收以的方式開啟的描述符。也就是說,pipefd[0] 是用於讀的,而 pipefd[1] 是用於寫的。

開啟了檔案描述符後,就可以使用 read(pipefd[0]) 和 write(pipefd[1]) 來讀寫資料了。

這兩個分別用於讀寫的描述符必須同時開啟才行,否則會出問題。

如果關閉讀 (close(pipefd[0])) 端保留寫端,繼續向寫端 (pipefd[1]) 端寫資料(write 函式)的程序會收到 sigpipe 訊號。

如果關閉寫 (close(pipefd[1])) 端保留讀端,繼續向讀端 (pipefd[0]) 端讀資料(read 函式),read 函式會返回 0.

當在程序用pipe函式開啟兩個描述符後,我們可以 fork 出乙個子程序。這樣,子程序也會繼承這兩個描述符,而且這兩個檔案描述符的引用計數會變成 2。(如果忘記了這個特性,請複習《fork 函式與檔案共享》 )

如果你需要父程序向子程序傳送資料,那麼得把父程序的 pipefd[0] (讀端)關閉,而在子程序中把 pipefd[1] 寫端關閉,反之亦然。為什麼要這樣做?實際上是避免出錯。傳統上 pipe 管道只能用於半雙工通訊(即一端只能發,不能收;而另一端只能收不能發),為了安全起見,各個程序需要把不用的那一端關閉(本質上是引用計數減 1)。

圖2 和圖 3 演示了上述過程。

要想實現全雙工通訊(既能發又能收)怎麼辦?你可以再使用 pipe 開啟兩個描述符,或者使用其它的 ipc 手段。

接下來,看例項。

下面的程式功能如下:父程序 fork 出乙個子程序,通過無名管道向子程序傳送字元,子程序收到資料後將字串中的小寫字元轉換成大寫並輸出。

為了突顯程式結構,刪除了錯誤處理部分的**。

// hellopipe.c

#include

#include

#include

#include

void child(int

*fd)

if (n == 0)

} exit(0);

}int main() ;

if (pipe(fd) < 0)

pid_t pid = fork();

if (pid == 0)

close(fd[0]);// 父程序關閉讀端

while (1)

} return

0;}

$ gcc hellopipe.c -o hellopipe

$ ./hellopipe

hello world // 輸入

hello world // 輸出

24215lkjl // 輸入

24215lkjl // 輸出

練習:在執行上面的程式時,分別 kill 父程序和子程序,看看有什麼結果,並解釋現象。

linux管道(無名管道)

首先管道是程序之間的乙個單向資料流,它的資料流向由核心管理,只能從乙個程序流向另外乙個程序,乙個程序向管道寫入資料,另外乙個程序從這個管道讀取資料。在使用管道 無名管道 時,只能用在父子程序或者親屬程序之間,若要用在任意程序之間則需要使用fifo 有名管道 如圖程序ab通過管道進行資料交換。程序a通...

Linux管道(無名管道)

是一套免費使用和自由傳播的類unix作業系統,是乙個基於posix和unix的多使用者 多工 支援多執行緒和多cpu的作業系統。它能執行主要的unix工具軟體 應用程式和網路協議。它支援32位和64位硬體。linux繼承了unix以網路為核心的設計思想,是乙個效能穩定的多使用者網路作業系統。它主要用...

無名管道性質

pipe函式。pipe buf ubunt下為65536.寫性質。讀端關閉時,寫入資料會受到核心傳來的sigpipe訊號。讀端未關閉,當管道內已經填滿了pipe buf而未有讀出時,則會阻塞在write函式中,直到管道另一邊有讀出則繼續寫入管道直到寫完。讀性質。寫端關閉時,read函式返回0.寫端存...