平行管道没有在C中关闭?

Posted

技术标签:

【中文标题】平行管道没有在C中关闭?【英文标题】:Parallel pipes not closing in C? 【发布时间】:2012-02-05 02:19:08 【问题描述】:

我正在尝试在 C 中并行管道,但由于某种原因它没有关闭......它只是在等待......不确定我是否描述得很好,因为我是新手,但这里是代码

... some code up here
if(child_pid == 0) 

    if(p0 >=0 && p1 == -1) 
        dup2(p0, STDIN_FILENO);
        close(p0);
        close(p1);
    
    else if (p0 == -1 && p1 >= 0) 
        dup2(p1, STDOUT_FILENO);
        close(p0);
        close(p1);
    
    else if (p0 >= 0 && p1 >=0) 
        dup2(p0, STDIN_FILENO);
        dup2(p1, STDOUT_FILENO);
        close(p0);
        close(p1);
    

      if (input)
        iofunc(input, 0);
      if (output)
        iofunc(output, 1);
    if (sub)
        command_exec (SUBSHELL_COMMAND, sub, -1, -1, -1);
        exit(0);
    
    else 
        execvp(w[0], w);
        exit(0);
    

else 
    if (waitpid (-1, &child_status, 0) != child_pid)
        child_status =-1;
    close(p0);
            close(p1);
     return WEXITSTATUS(child_status);

    ... some code down here

当 p0 == -1 && p1 >= 0 时,进程退出/返回,但由于某种原因,当 p0 >= 0 && p1 == -1 时,进程只是挂起并且管道没有关闭。我运行了一个命令 ls | cat 使用两个并行的子进程,ls 写入 p1,cat 从 p0 读取。输出是正确的,但是管道没有关闭,并且 cat 从未退出。怎么回事?

@William 我在父级 else 块中尝试了以下操作,但没有成功

close(p0);
close(p1);
if (waitpid (-1, &child_status, 0) != child_pid)
    child_status =-1;

@William 这里是调用上述代码的函数的代码

int i = 0;
    int num = 2;
    int status;
    pid_t pid;
    pid_t pids[num];
    int fd[2];
    int p = pipe(fd);
    int a;
    int b;
    //printf("pipe0:%d\n", fd[0]);
    //printf("pipe1:%d\n", fd[1]);

    for (i = 0; i < num; i++) 
      if ((pids[i] = fork()) < 0) 
        error(1,0, "child not forked");
       else if (pids[i] == 0) 
        if (i == 0)
            b = command_exec (c->type,
                c->u.command[1],
                0, f[0], p1);
        
        else if (i == 1)
            a = command_exec (c->type,
                c->u.command[0],
                1, p0, fd[1]);
        
        exit(a && b);
      

    

    while (num > 0) 
      pid = wait(&status);
      printf("Child with PID %ld exited with status 0x%x.\n", (long)pid, status);
      num--;


    

printf 只打印完成 ls 而不是 cat 的子进程

【问题讨论】:

您需要显示包含 pipe() 调用和 fork() 调用的代码。一旦与 cat 的标准输入关联的管道上的所有写入端文件描述符都关闭,cat 就会终止。您描述的这种问题几乎可以肯定是无法关闭文件描述符。可能 cat 本身的调用仍然打开它。 当你分叉时,父节点的管道两端都打开了。除非您在某个时候指定 p1 = fd[1],否则父级永远不会关闭 fd[1]。 Cat 将在父级关闭该文件描述符之前终止,因为 cat 正在等待更多数据。 【参考方案1】:

最有可能的是,父母正在打开管道的另一侧。 ls 在 cat 的管道写入端有一个打开的文件描述符,但父级也是如此。 cat 在所有写入端文件描述符都关闭之前不会退出。可能,您只需要在调用 waitpid 之前反转代码并关闭管道即可。

【讨论】:

以上是关于平行管道没有在C中关闭?的主要内容,如果未能解决你的问题,请参考以下文章

管道实现生产者消费者模型

如何在java中关闭当前工作目录(不是完整路径)[关闭]

以编程方式在 C 中检查 NIC 在 linux 中关闭时是不是有链接

如何在 C 中关闭指数符号?

eclipse如何在workspace中关闭、打开project?

发出警报后,我无法在我的反应本机应用程序中关闭我的键盘