【问题标题】:Loop unable to terminate while reading input through pipe in child process在子进程中通过管道读取输入时循环无法终止
【发布时间】:2019-12-30 15:13:51
【问题描述】:

我正在使用 C 进行管道实现。我必须编写 (grep -rF regex directory | tee output.txt | wc -l) 的 C 等效项。但是,代码无法继续超出 tee 等效项。 (以下代码中标记的循环永远不会终止)。我不明白为什么循环没有终止,为什么管道的输出没有传递给newpipe 的输入。

当我删除 while 循环时,程序终止,输出为 0。

    int newpipe[2],p[2],pid;
    char * argv_list1[] = {"grep","-rF","regex","directory",NULL};
    char * argv_list2[] = {"wc","-l",NULL};
    char *file="output.txt";
    pid=fork();
    if(pid==0){
        int pid2=fork();
        if(pid2==0){
            close(p[0]);
            dup2(p[1],1);
            execvp("grep",argv_list1);
        }
        else{
            wait(NULL);
            int fd=open(file, O_RDWR | O_CREAT |O_TRUNC,0666);
            close(newpipe[0]);
            close(p[1]);
            dup2(p[0], 0);
            printf("pid2=%d\n",pid2);
            dup2(newpipe[1],1);
            char tmp;
            while(read(p[0],&tmp,1)){
                write(fd,&tmp,1);
                write(1,&tmp,1);
            }//This loop never terminates and the output comes on standard output
            exit(1);
        }
    }
    else{
        wait(NULL);
        close(newpipe[1]);
        dup2(newpipe[0],0);
        execvp("wc",argv_list2);
    }

【问题讨论】:

    标签: c pipe fork system-calls child-process


    【解决方案1】:

    您发布的代码从不调用 pipe() 来创建管道;所以这是一个问题,但是在它发生之后,你还有更多的 fd 工作要做。

    在您的 第一个 孩子中,即 exec() 的 grep 中,您正确关闭 p[0],并将写入端 (p[1]) 复制到 STDOUT_FILENO(顺便说一句,a比 1) 更具描述性,但不要关闭 p[1]; dup2 就像一个副本而不是移动。这让它悬空。您可能会在最外层的进程中创建 newpipe,因此您必须在此处关闭它的两端。

    同样适用于tee,它需要关闭其未使用的fds,对于wc进程也是如此。

    您需要删除 wait,它们掩盖了一些 fd 处理错误。顺便说一句,请注意,在 tee 中,您将 p[0] 复制为 0,然后从 p[0] 读取。悬空管道不会产生 EOF。

    围绕 pipe() 和 fork() 处理 fd 总是很麻烦。在每个流程中逐一说明。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多