有名管道(FIFO)通訊機制完全攻略

2020-07-16 10:04:37
無名管道提供了一個簡單機制,允許一對進程通訊。然而,只有當進程相互通訊時,普通管道才存在。對於 UNIX 和 Windows 系統,一旦進程已經完成通訊並且終止了,那麼普通管道就不存在了。

有名管道提供了一個更強大的通訊工具。通訊可以是雙向的,並且父子關係不是必需的,當建立了一個有名管道後,多個進程都可用它通訊。

事實上,在一個典型的場景中,一個有名管道有幾個寫者。此外,當通訊進程完成後,有名管道繼續存在。雖然 UNIX 和 Windows 系統都支援有名管道,但是實現細節具有很大不同。下一步,我們探索這些系統的有名管道。

對於 UNIX,有名管道為 FIFO。一旦建立,它們表現為檔案系統的典型檔案。通過系統呼叫 mkfifo(),可以建立 FIFO,通過系統呼叫 open()、read()、write()和close(),可以操作 FIFO。

FIFO 會一直存在,直到它被顯式地從檔案系統中刪除。雖然 FIFO 允許雙向通訊,但只允許半雙工傳輸(資料在同一時間內只能按一個方向傳輸)。如果資料要在兩個方向上傳輸,那麼通常使用兩個 FIFO。此外,通訊進程應位於同一台機器上。如果需要不同系統之間的通訊,那麼應使用通訊端。

與 UNIX 系統相比,Windows 系統的有名管道通訊機制更加豐富。允許全雙工通訊(資料在同一時間內可在兩個方向上傳輸),並且通訊進程可以位於同一機器或不同機器。

此外,UNIX 的 FIFO 只支援位元組流的資料,而 Windows 系統允許位元組流或訊息流的資料。通過函數 CreateNamedPipe(),可建立有名管道;通過函數 ConnectNamedPipe(),客戶可連線到有名管道。通過函數 ReadFile() 和 WriteFile(),可進行有名管道的通訊。

管道使用

在使用 UNIX 命令列的情況下,管道經常用於將一個命令的輸出作為另一個命令的輸入。例如,UNIX 命令 ls 可以生成一個目錄列表。對於特別長的目錄列表,輸出可以有多個螢幕的長度。命令 more 管理輸出,一次一屏地顯示輸出;使用者通過按動空格鍵,一屏一屏地移動。

在命令 ls 和命令 more 之間(作為兩個獨立的進程執行)設定一個管道,以便允許將 ls 的輸出作為 more 的輸入,從而使用者就能一次一屏地顯示一個長的目錄列表。在命令列上,管道用字元“ | ”來表示。完整命令如下:

ls | more

在這種情況下,命令 ls 作為生產者,而命令 more 作為消費者。

Windows 為 DOS 外殼提供了一個命令 more,其功能與 UNIX 的類似。DOS 外殼也釆用“|”來表示管道。唯一不同的是,要得到一個目錄列表,DOS 利用命令 dir 而不是 ls,如下所示:

dir | more