FIFO(First In, First Out),又稱命名管道,是 Linux 進程間通訊(IPC)機制之一。與無名管道(pipe(),僅限親緣關係進程)不同,FIFO 在檔案系統中擁有路徑與 inode,任何知曉路徑的進程皆可開啟讀寫,極大擴展了適用場景。本文涵蓋建立方法(指令與系統呼叫)、核心特性、讀寫規則與典型應用模式。
| 特性 | FIFO (命名管道) | Pipe (無名管道) |
|---|---|---|
| 檔案系統實體 | 有(ls -l 顯示 p 型態) | 無(僅存在核心記憶體) |
| 存取方式 | 路徑名稱(open()、fopen()) | 檔案描述符傳遞(fork() 繼承) |
| 適用進程 | 任意無關進程 | 親緣進程(父子、兄弟) |
| 生命週期 | 檔案刪除前持續存在 | 進程結束自動銷毀 |
| 建立指令 | mkfifo, mknod | Shell |, pipe() 系統呼叫 |
mkfifo /tmp/my_fifo
# 或指定權限
mkfifo -m 600 /tmp/my_fifo
驗證:
ls -l /tmp/my_fifo
# prw-r--r-- 1 user user 0 Mar 15 10:30 /tmp/my_fifo|
p 表示 FIFO 型態,大小永遠為 0(資料在核心緩衝區流動)。
終端機 1(寫入端):
echo "Hello FIFO" > /tmp/my_fifo
# 此處阻塞,直到有讀取端開啟
終端機 2(讀取端):
cat /tmp/my_fifo
# 輸出: Hello FIFO
# 寫入端隨即解除阻塞結束
# 讀取端非阻塞(立即返回,無資料則 EOF)
cat /tmp/my_fifo &
# 寫入端
echo "test" > /tmp/my_fifo
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
const char *path = "/tmp/my_fifo";
// 1. 設定 umask 確保權限
mode_t old_mask = umask(0);
// 2. 移除舊檔案(避免 EEXIST)
unlink(path);
// 3. 建立 FIFO (mkfifo 相當於 mknod(path, S_IFIFO|mode, 0))
if (mkfifo(path, 0600) == -1) {
perror("mkfifo");
return 1;
}
umask(old_mask);
// 4. 開啟讀寫(注意:預設阻塞直到對端開啟)
int fd_write = open(path, O_WRONLY); // 阻塞直到有讀者
int fd_read = open(path, O_RDONLY); // 阻塞直到有寫者
// 5. 讀寫操作同一般檔案
write(fd_write, "data", 4);
char buf[128];
read(fd_read, buf, sizeof(buf));
close(fd_write);
close(fd_read);
unlink(path); // 清理
return 0;
}
write() ≤ PIPE_BUF(Linux 為 4096 bytes)保證原子寫入,不會與其他寫入者資料交錯。超過此大小可能分段。open():阻塞直到有寫入者開啟。open():阻塞直到有讀取者開啟。O_NONBLOCK):唯讀立即成功;唯寫若無讀者立即失敗返回 ENXIO。read() 返回 0(EOF)。若仍有寫入端開啟,read() 阻塞等待資料。SIGPIPE(預設終止進程),建議 signal(SIGPIPE, SIG_IGN) 搭配檢查 write() 返回 EPIPE。# 生產者腳本 (producer.sh)
while true; do
echo "$(date): sensor data" > /tmp/sensor_fifo
sleep 1
done
# 消費者腳本 (consumer.sh)
while read line; do
logger -t sensor "$line"
done < /tmp/sensor_fifo
/var/run/myserver/cmd_fifo),持續 read() 等待指令。open(O_WRONLY) 寫入指令(含回覆用的私有 FIFO 路徑)。# 主程式寫入單一 FIFO
exec 3> /tmp/log_fifo
echo "log entry" >&3
# 多個消費者分別處理
tee /tmp/log_fifo | grep ERROR | logger -t error &
tee /tmp/log_fifo | grep WARN | logger -t warn &
tee /tmp/log_fifo | cat > /var/log/full.log &
unlink() 移除 FIFO 檔案,避免殘留。O_CLOEXEC 旗標防止 exec() 時檔案描述符洩漏。socketpair() 或 Unix Domain Socket(支援雙向、傳遞檔案描述符、SCM_RIGHTS)。lsof /tmp/my_fifo 查看開啟進程。FIFO 以「有名稱、檔案系統可見、任意進程可存取」特性,彌補了無名管道侷限於親緣進程的缺口。掌握 mkfifo、阻塞語意、PIPE_BUF 原子性與 EOF 條件,即可靈活構建輕量級 IPC 通道。對於雙向通訊、高併發、需傳遞檔案描述符的場景,建議升級至 Unix Domain Socket。
Linux mkdir 提示「Read-only file system」三階段排查:掛載權限、檔案系統錯誤、硬體故障
建立 Swap 交換檔並設定開機自動掛載:dd 建立、mkswap 格式化、rc.local 加入啟動
Linux 終端 FTP 實戰指令大全:連線、列表、上傳、下載、切換目錄
Linux VMware 虛擬磁盤在線擴容實戰:無需重啟識別新空間
Ubuntu 安裝 NVIDIA 專有驅動並切換雙顯卡:效能模式與省電模式一鍵切換
Linux 環境變數 PATH 修改完全指南:臨時、永久、用戶級、系統級四種場景
Ubuntu Git 每次 push/pull 都要輸入密碼?設定 credential.helper store 永久快取認證