何时以及为什么我需要关闭管道?

3

我正在尝试理解管道,并且正在进行一个示例:


#define _XOPEN_SOURCE 700

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    pid_t p;
    int status;
    int pipefd[2];
    pipe(pipefd);
    p = fork();

    if(p == 0)
    {
        dup2(pipefd[1], 1);
        close(pipefd[0]);
        close(pipefd[1]);

        execlp(argv[1], argv[1], NULL); 
        perror(argv[1]);

        exit(1);
    }

    dup2(pipefd[0], 0);
    close(pipefd[0]);
    close(pipefd[1]);

    execvp(argv[2], argv + 2);
    perror(argv[2]);

    return 0;
}


我不明白为什么这段代码在使用管道之前会关闭它。
为什么我们要在这里调用close

你可能想要使用STDIN_FILENOSTDOUT_FILENOSTDERR_FILENO,而不是0、1和3。 - undefined
2个回答

7
dup2(pipefd[1], 1);
close(pipefd[0]);
close(pipefd[1]);

这将复制管道写入端的文件描述符到文件描述符#1,对应于标准输出 - 程序正常输出将进入此处。然后关闭了管道两端的原始文件描述符,但是:
  • 管道的写入端本身不会关闭,因为另一个打开的文件描述符(1)现在引用它
  • 该进程已分叉,并且子进程在关闭其自己的管道文件描述符之前同样复制了管道的读取端。这意味着在子进程中也保持打开管道的读取端。
通常情况下我们不一定需要关闭管道的原始文件描述符。然而,关闭我们不需要的文件描述符通常是一个好习惯,这就是该程序所做的事情。多个文件描述符可以引用同一个管道(或文件或其他实体),只有当所有引用它的文件描述符都关闭时,管道/文件/任何实体本身才会关闭。
此外,值得注意的是,只有在关闭管道的写入端(即引用它的所有打开文件描述符都被关闭)时,管道的读取端才会看到“文件结束”条件(即read返回0)。

3
你已经使用dup2调用复制了描述符,因此在子进程中不再需要pipefd[1]描述符。同样地,在父进程中也是如此。
实际上,描述符是有限的资源,如果你保持管道描述符打开状态,那么该进程就会少两个可用的描述符。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接