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

Linux 管道編程:popen() 與 pclose() 實現進程間通信

     編輯:關於C

popen() 封裝了 pipe()、fork()、exec(),以文件流 (FILE*) 形式提供單向管道,極大簡化「程序執行命令並讀取/寫入輸出」的開發。

函數原型


#include 

FILE *popen(const char *command, const char *type); // type: "r" 讀命令輸出, "w" 寫命令輸入
int pclose(FILE *stream); // 關閉流,等待子進程結束,返回狀態

讀取命令輸出示例 ("r" 模式)


#include 
#include 
#include 

#define BUFSZ 4096

int main() {
    char buf[BUFSZ];
    FILE *fp = popen("ls -la", "r"); // 執行命令,獲取輸出流
    if (!fp) { perror("popen"); return 1; }

    while (fgets(buf, BUFSZ, fp)) {
        fputs(buf, stdout); // 直接轉發到標準輸出
    }

    int status = pclose(fp);
    if (status == -1) perror("pclose");
    else printf("Command exited with status %d\n", WEXITSTATUS(status));
    return 0;
}

寫入命令輸入示例 ("w" 模式)


FILE *fp = popen("sort", "w"); // sort 從 stdin 讀取,排序後輸出到 stdout (終端)
if (fp) {
    fprintf(fp, "delta\nalpha\nepsilon\nbeta\ngamma\n");
    pclose(fp); // 關閉寫端,sort 收到 EOF 開始排序並輸出
}

雙向通信限制

popen() **只支援單向** ("r" 或 "w")。若需雙向 (同時讀寫),需手動 pipe() + fork() + dup2() + exec(),或使用 socketpair() / pty (偽終端)。

常見陷阱

  • 死鎖:父進程讀取大量輸出時,若不及時消費,管道緩衝區滿導致子進程阻塞寫入;父進程又在等待子進程結束 (pclose) → 死鎖。解決:非阻塞讀、多線程讀、或限制命令輸出量。
  • Shell 注入:command 經 /bin/sh -c 執行,用戶輸入若含 ; rm -rf / 等將被執行。**嚴禁**未過濾的用戶輸入拼接進 command。
  • 資源洩漏:必須調用 pclose() 回收子進程,否則產生殭屍進程。
  • 并發限制:標準實現使用全局文件表,多線程同時 popen 可能衝突,高併發場景建議自行管理管道。

對比:system() vs popen() vs 手動管道

函數返回值交互能力適用場景
system()命令退出狀態無 (輸出直接到終端)簡單執行無需捕獲輸出
popen()FILE* 流單向 (讀或寫)需捕獲輸出/提供輸入
手動 pipe/fork/exec自定義雙向、多管道、重定向控制複雜 IPC、高性能、安全要求高
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved