行程間通訊

具名管線(named pipe / FIFO)

/ FY-foh /

匿名管線是親屬之間的私人水管——你只能把它交給自己的子行程。但如果兩個毫不相干、在不同時間由不同人啟動的程式需要傳資料呢?具名管線的解法是給管線一個檔案系統裡的名字。它是一個有固定位址的會合點:任何知道路徑的人都能來連上。

你用 mkfifo mypipe(或 mkfifo() 呼叫)建立一個。這會在目錄裡造出一個特殊檔案——ls 看得到它,ls -l 會以開頭的 p 標示它——但它不是普通檔案:它在磁碟上不存任何資料。它只是一個會合用的名字。一個程式以讀取模式開啟它、另一個以寫入模式開啟它,從此它的行為就跟匿名管線一模一樣:單向、有序的位元組流,沒有訊息邊界,緩衝於核心。關鍵的巧妙之處在於 open() 如何阻塞:以讀取模式開啟一個 FIFO 會等到有寫入方也開啟它(反之亦然),於是兩端在會合點同步。這正是重點所在——無親屬關係的行程靠名字找到彼此。

FIFO 適合簡單的本機接管線:一個長時間執行的資料生產者寫入 /tmp/feed,任何消費者從那裡讀,完全不需要父子關係。它的注意事項與匿名管線同源,再加上幾點。它仍是單向的(要雙向就開兩個 FIFO)、仍然沒有訊息分框、若在無讀取方時寫入仍會引發 SIGPIPE。又因為行程結束後名字仍留在磁碟上,你必須自己移除它(rm 或 unlink()),不像匿名管線在描述符關閉時就消失。

$ mkfifo /tmp/feed # 終端機 1 $ cat < /tmp/feed # 在此等待寫入方 $ echo hello > /tmp/feed # 終端機 2——「hello」此時出現在終端機 1

檔案系統裡的一個名字讓兩個陌生人相遇。讀取方在 open() 阻塞,直到寫入方出現。

FIFO 有名字卻不存資料——這個檔案只是會合點。別把它跟普通檔案搞混:讀兩次 FIFO 不會重讀舊資料;位元組一旦被讀走就沒了,跟管線完全一樣。

又称
FIFOfifo special file具名管線FIFO 特殊檔案