Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學

Linux 進程間通訊:管道與有名管道 (FIFO) 機制深度解析與程式驗證

編輯:Linux 系統常見問題解答

管道是 Unix 最早的 IPC 機制。本文系統梳理無名管道(親緣進程)與有名管道 FIFO(非親緣進程)的建立、讀寫規則、原子性保證,並提供 C 語言驗證程式碼片段。

管道核心特性對比

特性無名管道 (pipe)有名管道 (FIFO/mkfifo)
適用對象親緣進程 (父子、兄弟)任意進程 (無親緣限制)
命名空間無名稱,僅存在記憶體檔案系統路徑 (如 /tmp/myfifo)
建立方式pipe(int fd[2])mkfifo(path, mode) 或 shell mkfifo
生命週期隨進程結束銷毀檔案持久存在,除非手動刪除
雙向通訊需建立兩個管道同理,或雙方開啟同一 FIFO 讀寫

無名管道 API 與讀寫規則


#include 
int pipe(int fd[2]);  // 成功返回 0,fd[0]=讀端, fd[1]=寫端

典型用法:父進程 pipe() → fork() → 父關讀端寫資料、子關寫端讀資料 (或相反)。

讀端規則 (fd[0])

  • 寫端全部關閉 → read() 返回 0 (EOF)
  • 請求位元組 > PIPE_BUF (POSIX ≥512B, Linux 4096B) → 返回現有資料 (可能 < 請求量)
  • 請求位元組 ≤ PIPE_BUF → 阻塞直到滿足或 EOF

寫端規則 (fd[1])

  • 讀端存在 → 寫入追加至緩衝區尾部,緩衝區滿則阻塞
  • 讀端全部關閉 → 寫進程收到 SIGPIPE (預設終止),write() 返回 EPIPE
  • 單次寫入 ≤ PIPE_BUF → 原子性保證 (不會與其他寫入交錯)
  • 單次寫入 > PIPE_BUF → 不保證原子性,可能被其他寫入插入

有名管道 (FIFO) 建立與使用


// 程式建立
#include 
mkfifo("/tmp/myfifo", 0666);

// Shell 建立
mkfifo /tmp/myfifo

// 開啟方式 (阻塞預設)
int fd = open("/tmp/myfifo", O_RDONLY);  // 讀端:阻塞直到有寫端開啟
int fd = open("/tmp/myfifo", O_WRONLY);  // 寫端:阻塞直到有讀端開啟

// 非阻塞開啟
open("/tmp/myfifo", O_RDONLY | O_NONBLOCK);

驗證程式碼片段:管道讀寫行為


// readtest.c - 驗證讀端規則
#include 
#include 
#include 

int main() {
    int fd[2];
    pipe(fd);
    if (fork() == 0) {  // 子進程:寫端
        close(fd[0]);
        write(fd[1], "hello", 5);
        close(fd[1]);
        _exit(0);
    }
    close(fd[1]);  // 父進程:讀端
    char buf[100];
    int n = read(fd[0], buf, sizeof(buf));
    printf("Read %d bytes: %.*s\n", n, n, buf);  // 輸出: Read 5 bytes: hello
    return 0;
}

常見陷阱與最佳實踐

  • 死鎖:雙方同時等待對方寫入/讀取 → 設計明確的協定 (請求/回應、長度前綴)
  • 殭屍讀端:忘記關閉不需要的管道端 → 導致對方永不收到 EOF → 永久阻塞
  • 緩衝區滿阻塞:大量資料需非阻塞 I/O + select/poll/epoll 處理
  • SIGPIPE 處理:signal(SIGPIPE, SIG_IGN) 避免寫端斷開時進程被殺
  • 原子寫入:日誌、指令傳遞請保持單次 write() ≤ PIPE_BUF

現代替代方案

  • Unix Domain Socket:雙向、支援 sendmsg 傳遞檔案描述符、效能更高
  • message queue (mq_*):訊息優先級、非阻塞、持久化選項
  • shared memory + semaphore:大資料量零拷貝

管道雖古老,但簡單、可靠、Shell 原生支援,仍是進程協作、Shell 管線、容器標準輸入輸出重導向的基石。掌握其讀寫語意,是系統程式設計師的必修功課。

Copyright © Windows教程網 All Rights Reserved