2013-04-24 60 views
0

我有一個使用fork()和pipe()的標準程序,目的是爲子進程中的第三方程序調用system()調用並將輸出重定向到父進程。我發現如果我這樣做,父進程永遠不會檢測到子進程已關閉管道,因此它永遠不能從調用read()的while循環中退出。在Linux中,使用pipe()從分叉進程調用system()

當我使用其他一些通用系統調用(如「ls -l」)替換system()調用第三方程序時,問題消失。使用system()影響此程序的第三方程序調用可能存在什麼潛在問題?

#include <iostream> 
#include <fstream> 
#include <stdlib.h>//system 
#include <sys/wait.h> 

int main(int argc, char **argv){ 

    //setup pipe 
    int pipeid_L1[2]; 
    pipe(pipeid_L1); 

    pid_t pid_L1; 
    pid_L1 = fork(); 
    if(pid_L1==-1){ 
    throw std::logic_error("Fork L1 failed"); 
    } 
    else if(pid_L1 ==0){//L1 child process 
    dup2(pipeid_L1[1],STDOUT_FILENO);//redirect standard out to pipe 
    close(pipeid_L1[0]); //child doesn't read 
    system(... some program ...); //making the system call to a third party program 
    close(pipeid_L1[1]); 
    exit(0); 
    } 
    else{ 

    //setup pipe 
    close(pipeid_L1[1]);  

    int buf_size=64; 
    char L1_buf[buf_size]; 

    while(read(pipeid_L1[0],L1_buf,buf_size)){ //this while loop never exits if I make the system call to the third party program 
     ... do stuff here ... 
    } 


    } 
    exit(EXIT_SUCCESS); 
} 

回答

1

問題是,只有在所有其他進程關閉管道的寫入結束時,父級纔會看到EOF。有三個相關的過程 - 您分叉的孩子,系統分叉和執行的shell以及您運行的實際程序。在程序實際退出之前,前兩個將不會關閉管道的末端,因此在這種情況發生並且所有進程都退出之前,父級將不會看到EOF。

如果您希望父程序在程序關閉其標準輸出後立即看到EOF,而不是等到它退出,則需要使用exec而不是system來消除這些額外的進程。

或者,您可以使用popen,它可以爲您執行所有所需的fork/pipe/exec。