首页 > 解决方案 > 父子进程之间的管道问题

问题描述

使用管道,父亲从标准输入读取并使用管道将其发送到子进程,以便子进程可以对输入执行 wordcount。打开和关闭管道 p[0] 和 p[1] 的问题。为什么我不能 dup2(p[1],1) 然后 write(1,buffer,1)?仅当我在没有 dup2(p[1],1) 的情况下执行 write(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;
}

标签: cpipedup2

解决方案


为什么我不能 dup2(p[1],1) 然后 write(1,buffer,1)?

你可以,虽然它看起来毫无意义。但是,如果您尝试使用(仅)写入标准输出的 I/O 函数之一,这将更有意义。

仅当我在没有 dup2(p[1],1) 的情况下执行 write(p[1],buffer,1) 时才有效。

这取决于您所说的“作品”是什么意思。当我运行您的原始代码时,程序从不打印任何输出并且从不终止,但这并不意味着父级的写入没有成功地将数据发送给子级。

问题是孩子不知道何时到达输入的末尾。它正在等待其输入端的文件结束信号,只要有任何打开的文件描述符与管道的写端相关联,它就不会出现。

如果父级没有欺骗管道的写端,那么它只打开了一个文件描述符,而子级有一个。两者都在适当的时候关闭它们。但是在您提供的代码中,父级p[1]复制到文件描述符 1,因此它有两个打开的文件描述符指向管道端。它只会关闭p[1],使文件描述符 1 保持打开状态,因此子进程一直在等待更多输入。

如果 FD 1 退出,父级将关闭它,允许子级完成,但它正在等待子级先终止。这是与 I/O 重定向相关的更常见的死锁错误之一。我建议不要让父级复制文件描述符,因为复制到 FD 1 会不必要地阻止它将其标准输出用于任何其他目的。但是如果它确实欺骗了它,那么它必须在子进程终止之前关闭两个文件描述符。


推荐阅读