Linux/Unix 系統中的命名管道或 FIFO 是什麼?


管道旨在用於相關程序之間的通訊。我們不能將管道用於不相關程序的通訊。然後,要實現不相關程序的通訊,簡單的答案就是命名管道。即使這適用於相關程序,但將命名管道用於相關程序的通訊也沒有意義。

與管道不同,我們可以使用單個命名管道來進行雙向通訊(伺服器和客戶端之間的通訊,以及客戶端和伺服器在同一時間進行通訊),因為命名管道支援雙向通訊。

命名管道的另一個名稱是**FIFO(先進先出)**。讓我們看看建立命名管道的系統呼叫(mknod()),它是一種特殊檔案。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int mknod(const char *pathname, mode_t mode, dev_t dev);

此係統呼叫將建立特殊檔案或檔案系統節點,例如普通檔案、裝置檔案或 FIFO。系統呼叫的引數是路徑名、模式和裝置。路徑名以及模式和裝置資訊的屬性。如果未指定目錄,則路徑名是相對的,它將在當前目錄中建立。指定的模式是檔案的模式,它指定檔案型別,例如檔案型別和檔案模式,如以下表格中所述。dev 欄位用於指定裝置資訊,例如主裝置號和次裝置號。

檔案型別描述檔案型別描述
S_IFBLK塊特殊檔案S_IFREG普通檔案
S_IFCHR字元特殊檔案S_IFDIR目錄
S_IFIFOFIFO 特殊檔案S_IFLNK符號連結


檔案模式描述檔案模式描述
S_IRWXU
所有者具有讀、寫、執行/搜尋許可權
S_IWGRP
組具有寫許可權
S_IRUSR
所有者具有讀許可權
S_IXGRP
組具有執行/搜尋許可權
S_IWUSR
所有者具有寫許可權
S_IRWXO
組具有執行/搜尋許可權
S_IXUSR
所有者具有執行/搜尋許可權
S_IROTH
其他人具有讀許可權
S_IRWXG
組具有讀、寫、執行/搜尋許可權
S_IWOTH
其他人具有寫許可權
S_IRGRP
組具有讀許可權
S_IXOTH
其他人具有執行/搜尋許可權

檔案模式也可以用八進位制表示法表示,例如 0XYZ,其中 X 表示所有者,Y 表示組,Z 表示其他人。X、Y 或 Z 的值可以介於 0 到 7 之間。讀、寫和執行的值分別為 4、2、1。如果需要讀、寫和執行的組合,則相應地新增值。

例如,如果為 0640,則表示所有者具有讀寫許可權 (4 + 2 = 6),組具有讀許可權 (4),其他人沒有許可權 (0)。

如果成功,此呼叫將返回零;如果失敗,則返回 -1。要了解失敗的原因,請檢查 errno 變數或 perror() 函式。

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode)

此庫函式建立一個 FIFO 特殊檔案,用於命名管道。此函式的引數是檔名和模式。檔名可以是絕對路徑或相對路徑。如果未給出完整路徑名(或絕對路徑),則檔案將在正在執行的程序的當前資料夾中建立。檔案模式資訊如 mknod() 系統呼叫中所述。

如果成功,此呼叫將返回零;如果失敗,則返回 -1。要了解失敗的原因,請檢查 errno 變數或 perror() 函式。

讓我們考慮一個在終端上執行伺服器並在另一個終端上執行客戶端的程式。該程式只會執行單向通訊。客戶端接受使用者輸入並將訊息傳送到伺服器,伺服器在輸出上列印訊息。該過程將持續進行,直到使用者輸入字串“end”。

讓我們透過一個例子來理解這一點 -

**步驟 1** - 建立兩個程序,一個是 fifoserver,另一個是 fifoclient。

**步驟 2** - 伺服器程序執行以下操作 -

  • 建立名為“MYFIFO”的命名管道(使用系統呼叫 mknod()),如果尚未建立。

  • 以只讀方式開啟命名管道。

  • 這裡,建立的 FIFO 對所有者具有讀寫許可權,對組具有讀許可權,對其他人沒有許可權。

  • 無限期地等待來自客戶端的訊息。

  • 如果從客戶端接收到的訊息不是“end”,則列印該訊息。如果訊息是“end”,則關閉 fifo 並結束程序。

**步驟 3** - 客戶端程序執行以下操作 -

  • 1) 以只寫方式開啟命名管道。

  • 2) 接受使用者的字串。

  • 3) 檢查使用者是否輸入“end”或除“end”之外的其他內容。無論哪種方式,它都會向伺服器傳送訊息。但是,如果字串是“end”,則關閉 FIFO 並結束程序。

  • 4) 無限期地重複,直到使用者輸入字串“end”。

使用命名管道進行雙向通訊

管道之間的通訊應該是單向的。通常,管道僅限於單向通訊,並且需要至少兩個管道才能進行雙向通訊。管道僅用於相關程序。管道不能用於不相關程序的通訊,例如,如果我們想在一個終端上執行一個程序,在另一個終端上執行另一個程序,則管道無法實現。命名管道旨在用於兩個或多個不相關程序之間的通訊,並且還可以進行雙向通訊。

我們已經看到了命名管道之間的單向通訊,即從客戶端到伺服器的訊息。現在,讓我們看一下雙向通訊,即客戶端向伺服器傳送訊息,伺服器接收該訊息並使用相同的命名管道將另一條訊息傳送回客戶端。

以下是一個示例 -

**步驟 1** - 建立兩個程序,一個是 fifoserver_twoway,另一個是 fifoclient_twoway。

**步驟 2** - 伺服器程序執行以下操作 -

  • 在 /tmp 目錄中建立名為“fifo_twoway”的命名管道(使用庫函式 mkfifo()),如果尚未建立。

  • 以讀寫方式開啟命名管道。

  • 這裡,建立的 FIFO 對所有者具有讀寫許可權,對組具有讀許可權,對其他人沒有許可權。

  • 無限期地等待來自客戶端的訊息。

  • 如果從客戶端接收到的訊息不是“end”,則列印該訊息並反轉字串。反轉後的字串將傳送回客戶端。如果訊息是“end”,則關閉 fifo 並結束程序。

**步驟 3** - 客戶端程序執行以下操作 -

  • 以讀寫方式開啟命名管道。

  • 接受使用者的字串。

  • 檢查使用者是否輸入“end”或除“end”之外的其他內容。無論哪種方式,它都會向伺服器傳送訊息。但是,如果字串是“end”,則關閉 FIFO 並結束程序。

  • 如果傳送的訊息不是“end”,則等待來自客戶端的訊息(反轉後的字串)並列印反轉後的字串。

  • 無限期地重複,直到使用者輸入字串“end”。

更新於: 2019年10月11日

3K+ 閱讀量

開啟你的職業生涯

透過完成課程獲得認證

開始學習
廣告
© . All rights reserved.