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

C語言進程間通信實戰:使用管道實現數據交換(上)

     編輯:關於C語言

C語言進程間通信實戰:使用管道實現數據交換(上)

各位讀者大家好,上一篇我們介紹了管道進行進程間通信的基本概念,本篇將深入講解第一種管道——偽管道的具體使用方法。讓我們繼續探索C語言進程通信的奧秘!

什麼是偽管道?

所謂「偽管道」,是指通過 popen 和 pclose 這兩個標準庫函數來創建和管理管道。它之所以被稱為「偽管道」,是因為 popen 的參數是一個 Linux 終端命令字符串,它通過啟動 Shell 來執行該命令,本質上與終端中使用「|」管道符的效果相同,但性能相對較低。

核心函數詳解

popen 函數原型

FILE *popen(const char *command, const char *open_mode);
  • command:要執行的 Shell 命令字符串,可根據程序需求傳入不同命令。
  • open_mode:管道打開模式,只能是 "r"(讀)或 "w"(寫)。
  • 返回值:文件流指針(FILE*),可像操作普通文件一樣使用 fread/fwrite 等函數進行數據讀寫。

通過傳入 env、grep 等 Linux 命令,popen 會啟動相應的子進程,主進程即可通過返回的文件流與子進程進行數據交換。

pclose 函數原型

int pclose(FILE *stream);
  • stream:由 popen 返回的文件流指針。
  • 返回值:關聯進程結束時的退出碼。

該函數用於關閉 popen 打開的管道,釋放資源,通常在進程結束前調用。

偽管道使用步驟

  1. 調用 popen 打開管道,指定讀/寫模式。
  2. 使用 fread/fwrite 進行數據讀寫。
  3. 調用 pclose 關閉管道。

實戰代碼示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char buffer[BUFSIZ + 1];
    int read_count = 0;
    FILE *p_read, *p_write;

    memset(buffer, '\0', sizeof(buffer));

    // 以讀模式打開管道,執行 env 命令獲取環境變量
    p_read = popen("env", "r");
    if (NULL == p_read) {
        printf("open pipe for reading failed\n");
        return 1;
    }

    // 以寫模式打開管道,執行 grep bash 過濾包含 bash 的行
    p_write = popen("grep bash", "w");
    if (NULL == p_write) {
        printf("open pipe for writing failed\n");
        return 1;
    }

    // 從 env 進程讀取數據,寫入 grep 進程
    read_count = fread(buffer, sizeof(char), BUFSIZ, p_read);
    while (read_count > 0) {
        fwrite(buffer, sizeof(char), strlen(buffer), p_write);
        read_count = fread(buffer, sizeof(char), BUFSIZ, p_read);
    }

    pclose(p_read);
    pclose(p_write);
    return 0;
}

進程間數據流向解析

為了釐清讀寫模式的看似矛盾之處,我們假設三個進程:

  • 進程 A:主程序(main 函數)
  • 進程 B:env 命令啟動的子進程
  • 進程 C:grep bash 命令啟動的子進程
  1. 進程 A 以 讀模式 ("r") 打開管道並啟動進程 B。這意味著進程 A 可以從管道中讀取進程 B 的標準輸出(即 env 的執行結果)。
  2. 進程 A 將讀取到的數據存入緩衝區。
  3. 進程 A 以 寫模式 ("w") 打開另一管道並啟動進程 C。這意味著進程 A 可以向管道寫入數據,這些數據將成為進程 C 的標準輸入。
  4. 進程 C 從管道讀取數據(即進程 B 的輸出),經 grep 過濾後輸出結果。

這樣就實現了:env 產生數據 → 主進程中轉 → grep 處理數據 → 最終輸出,完成進程間通信。

運行結果驗證

$ ./pipe_demo
SHELL=/bin/bash

對比終端直接執行管道命令:

$ env | grep bash
SHELL=/bin/bash

兩者結果完全一致,驗證了偽管道的效果等同於 Shell 管道操作。

完整代碼已上傳至資源庫,歡迎下載實踐。下一篇我們將介紹「入門級管道」——使用 pipe 系統調用配合 fork 實現父子進程通信,敬請期待!

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