首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Unix 進程間通信實戰:管道實現標準 I/O 重定向

     編輯:關於C語言

管道通信模型

管道與標準 I/O 重定向核心原理

Unix 中一切皆文件。標準輸入(stdin, fd 0)、標準輸出(stdout, fd 1)、標準錯誤(stderr, fd 2)本質是預打開的文件描述符。利用 dup2(oldfd, newfd) 可將任意文件描述符複製到標準描述符位置,實現透明重定向:

dup2(fd1, 0); // 標準輸入 ← fd1
dup2(fd2, 1); // 標準輸出 → fd2
dup2(fd3, 2); // 標準錯誤 → fd3

父子進程管道通信標準模型(父 stdout → 子 stdin)

  1. 創建管道:pipe(fildes) 返回 fildes[0](讀端)、fildes[1](寫端)。
  2. Fork 子進程:子進程繼承管道描述符。
  3. 父進程:關閉讀端 fildes[0],將 stdout(1) 重定向到寫端 fildes[1]。
  4. 子進程:關閉寫端 fildes[1],將 stdin(0) 重定向到讀端 fildes[0]。

父子進程管道流向圖

完整實戰代碼

#include <unistd.h>
#include <stdio.h>

int main() {
    int fildes[2];
    pid_t pid;
    char buf[256];

    if (pipe(fildes) < 0 || (pid = fork()) < 0) {
        fprintf(stderr, "pipe/fork failed\n");
        return 1;
    }

    if (pid == 0) {                 // 子進程
        close(fildes[1]);           // 關閉寫端
        dup2(fildes[0], 0);         // stdin ← 管道讀端
        close(fildes[0]);
        gets(buf);                  // 實際讀取父進程 stdout
        fprintf(stderr, "child:[%s]\n", buf);
        return 2;
    }

    // 父進程
    close(fildes[0]);               // 關閉讀端
    dup2(fildes[1], 1);             // stdout → 管道寫端
    close(fildes[1]);
    puts("Hello!");                 // 輸出自動流向子進程 stdin
    return 0;
}

運行結果驗證

# ./pipe3
child:[Hello!]

父進程 puts("Hello!") 未顯示在終端,而是經管道傳給子進程,子進程 gets() 讀取後打印到 stderr,驗證重定向成功。

進階應用場景

  • Shell 管道實現:cmd1 | cmd2 本質是將 cmd1 stdout 接 cmd2 stdin。
  • 進程沙箱/監控:父進程捕獲子進程所有輸出進行過濾、記錄或策略控制。
  • 無縫對接舊程序:無需修改子進程代碼,外部注入輸入/捕獲輸出。

關鍵細節提醒

  • 必須在 fork 後、exec 前 完成關閉/重定向操作,避免描述符洩漏或死鎖。
  • 雙向通信需創建 兩條管道(父→子、子→父)。
  • 生產環境建議使用 socketpair(AF_UNIX, SOCK_STREAM, 0, fds) 替代管道,支持全雙工、可傳遞文件描述符。

掌握管道重定向模型,是編寫高可靠 Unix 系統工具、服務器框架、自動化測試平台的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved