父亲使用管道读取标准输入,并使用管道将其发送到子进程,以便子进程可以对输入执行字数统计。 打开和关闭管道p [0]和p [1]的问题。 为什么我不能dup2(p [1],1)然后写(1,buffer,1)?仅当我不使用dup2(p [1],1)来写(p [1],buffer,1)时,它才起作用。
int main(int argc, char **argv){
int p[2];
int n;
char buffer[1024];
pipe(p);
if(!fork()){
close(p[1]);
dup2(p[0],0);
close(p[0]);
execlp("wc","wc",NULL);
_exit(0);
}
else{
close(p[0]);
dup2(p[1],1);
while((n=read(0,buffer,1))>0){
write(1,buffer,1);
}
close(p[1]);
wait(NULL);
}
return 0;
}
答案 0 :(得分:0)
为什么我不能dup2(p [1],1)然后写(1,buffer,1)?
您可以,尽管似乎毫无意义。但是,如果您尝试使用一种(仅)向stdout写入的I / O函数,那将更有意义。
仅当我不写dup2(p [1],1)的情况下写(p [1],buffer,1)时才起作用。
这取决于您所说的“作品”。当我运行您的原始代码时,该程序从不打印任何输出,也不会终止,但这并不意味着父级的写入未成功将数据发送给子级。
问题是孩子不知道何时到达输入的结尾。它正在等待其输入上的文件结束信号,只要与管道的写入端关联的任何打开文件描述符就不会出现。
如果父级不复制管道的写入端,则仅在其上打开一个文件描述符,而子级则具有一个。双方都在适当的时候关闭了它们。但是在您提供的代码中,父级将p[1]
复制到文件描述符1上,因此它有两个指向管道末端的打开文件描述符。它只会关闭p[1]
,而文件描述符1保持打开状态,因此子级将继续等待更多输入。
如果退出,则父级将关闭FD 1,以允许孩子完成操作,但它正在等待孩子先终止。这是与I / O重定向相关的更常见的死锁错误之一。我建议您不要让父对象复制文件描述符,因为复制到FD 1上会不必要地阻止它将其标准输出用于任何其他目的。但是,如果确实重复,则必须在子项终止之前关闭两个文件描述符。