我有一个使用fork()和pipe()的标准程序,目的是在子进程中为第三方程序调用system()并将输出重定向到父进程。我发现,如果我这样做,不管怎样,父进程永远不能检测到子进程已经关闭了管道,因此它永远不能从调用read()的while循环中退出。
当我用一些其他通用系统调用系统(“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);
}
答案 0 :(得分:1)
问题是,当所有其他进程关闭管道的写入端时,父进程才会看到EOF。有三个相关的过程 - 你分叉的孩子,系统分叉和执行的shell,以及你运行的实际程序。在程序实际退出之前,前两个将不会关闭管道的末尾,因此在发生这种情况并且所有进程都退出之前,父级将不会看到EOF。
如果您希望父级在程序关闭其标准输出后立即查看EOF,而不是等到它退出,则需要使用exec
而不是{{}来消除这些额外的进程。 1}}。
或者,您可以使用system
为您执行所有需要的fork / pipe / exec。