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

C語言進程間通信:匿名管道 pipe() 實現父子進程數據傳輸

     編輯:關於C

匿名管道 pipe() 是父子進程通信的標準方式:內核創建一對文件描述符 fd[0](讀端)、fd[1](寫端),fork() 後雙方繼承描述符,關閉各自不用的一端,形成單向數據流。本文給出標準「創建→fork→關閉無用端→讀寫→同步」完整流程代碼。

pipe() API

#include 
int pipe(int fd[2]);
// 成功返回 0,fd[0]=讀端,fd[1]=寫端
// 失敗返回 -1,設置 errno

標準使用步驟

  1. pipe(fd) 創建管道。
  2. fork() 創建子進程,父子雙方擁有相同 fd[0], fd[1]。
  3. 關鍵:父進程關閉 fd[1](寫端),子進程關閉 fd[0](讀端),避免死鎖與 EOF 誤判。
  4. 子進程 write(fd[1], ...) 發送數據。
  5. 父進程 read(fd[0], ...) 接收數據。
  6. 父進程 wait() 同步等待子進程結束(可選,視邏輯)。

完整代碼

#include 
#include 
#include 
#include 
#include 

#define BUFSIZ 1024

int main() {
    char input[] = "IPC by pipe";
    char output[BUFSIZ+1] = {0};
    int fd[2];
    int count = 0;
    pid_t pid, pid_res;
    int stat_value;

    // 1. 創建管道
    if (pipe(fd) == -1) {
        perror("pipe");
        return 1;
    }

    // 2. 創建子進程
    pid = fork();
    if (pid < 0) {
        perror("fork");
        return 1;
    }

    if (pid > 0) {  // 父進程:讀取
        close(fd[1]);  // 關閉寫端,關鍵!
        pid_res = wait(&stat_value);  // 等待子進程寫入結束
        if (pid_res > 0) {
            count = read(fd[0], output, BUFSIZ);
            printf("Father read %d bytes: %s\n", count, output);
            close(fd[0]);
        }
    } else {  // 子進程:寫入
        close(fd[0]);  // 關閉讀端,關鍵!
        count = write(fd[1], input, strlen(input));
        printf("Son wrote %d bytes: %s\n", count, input);
        close(fd[1]);
        exit(0);
    }

    return 0;
}

運行結果

Son wrote 12 bytes: IPC by pipe
Father read 12 bytes: IPC by pipe

關鍵點深度解析

為什麼必須關閉無用端?

  • 讀端關閉寫端:父進程若不關閉 fd[1],自己也持有寫端,導致管道永遠有寫端打開,read() 永遠讀不到 EOF(返回 0),會無限阻塞。
  • 寫端關閉讀端:子進程若不關閉 fd[0],雖不影響寫入,但浪費描述符,且若父進程異常退出未關閉讀端,子進程寫入可能觸發 SIGPIPE。

同步機制:wait()

父進程調用 wait() 阻塞,直到子進程 exit()。這保證:

  1. 子進程完成 write 並 close(fd[1]) 發送 EOF。
  2. 父進程 read 讀到數據後再繼續,避免競態。

常見錯誤與修正

錯誤代碼後果修正
父子均不關閉無用端read 永不返回 EOF,死鎖各關閉自己不用的端
父進程先 read 再 wait若子進程寫慢,read 阻塞正常;但無 wait 會產生殭屍進程保留 wait 或用 SIGCHLD 處理
缓衝區大小不足write 可能阻塞或部分寫入循環 write 直到全部寫完

總結

匿名管道 pipe() 是父子進程通信的輕量級標準方案:

  1. pipe(fd) 一對描述符。
  2. fork() 共享描述符。
  3. 各關閉無用端(核心紀律)。
  4. write/read 數據流。
  5. wait() 同步清理。

掌握這套「管道六步法」,即可構建高性能、無競態的父子進程數據通道。

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