fd [0]之后的dup2!= STDIN_FILENO

时间:2013-03-28 08:43:09

标签: c linux pipe

有人可以在检查fd [0]!= STDIN_FILENO之后解释使用dup2的原因,因为根据我的理解fd [0]!= STDIN_FILENO会失败而且dup2仍然会返回STDIN_FILENO以外的东西,只是试图了解一些示例代码谢谢,如果有人可以解释我对excelp的使用那将是非常棒的。

int fd[2];
pid_t pid;

if(argc != 2) {
        fprintf(stderr, "Must be specify exactly 1 file\n");
        exit(0);
    }

    if(pipe(fd) < 0)
        exit(1);./ 

    pid = fork();

    switch (pid) {
        case -1:
            exit(1);
        case 0:
            close(fd[1]);
                        //here
            if(fd[0] != STDIN_FILENO) {
                if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
                    exit(3);
                close(fd[0]);
            }
            if(execlp("tr", "tr", "[a-z]", "[A-Z]", (char *) 0) < 0)
                exit(4);
            break;

        default:
            close(fd[0]);
                        // and here
            if(fd[1] != STDIN_FILENO) {
                if(dup2(fd[1], STDIN_FILENO) != STDIN_FILENO)
                    exit(5);
                close(fd[1]);
            }
            if(execlp("cat", "cat", argv[1], (char *) 0) < 0)
                exit(4);
            break;
    }
    return 0;

4 个答案:

答案 0 :(得分:2)

目的是使stdin(STDIN_FILENO,为0)指向fd [0]指向的文件(管道的读取侧)。首先检查它们是否已经相同...如果是,代码将重复0到0然后关闭0 - 不好。如果它们不相同,请使用dup2使STDIN_FILENO指向fd [0]指向的位置。如果dup2成功,它将返回其第二个参数,因此如果dup2失败,则通过调用退出该检查。

你写

  

根据我的理解fd [0]!= STDIN_FILENO会失败

为什么你“理解”这一点并不清楚。它仅在fd [0]包含STDIN_FILENO(即0)时失败,但由于它包含pipe调用分配的文件描述符,因此不太可能。

  

dup2仍将返回STDIN_FILENO以外的其他内容

如果成功,dup2将返回其第二个参数。它除了失败之外不会返回STDIN_FILENO以外的东西 - 为什么会这样? - 在这种情况下,它返回-1。

答案 1 :(得分:1)

execlp基本上执行一个程序。该程序将从STDIN_FILENO读取其输入(换句话说,fd 0)。 dup2close系统调用用于将fd[0]fd[1]文件描述符移动到该数字。

答案 2 :(得分:1)

fd[0] != STDIN_FILENO的检查是一种防御性编程实践,因为通常标准输入和标准输出先前已打开,但如果它们在您pipe()调用之前已关闭,{{ 1}}会将两个描述符分配给管道(注意,当创建管道时,用于管道两端的文件描述符是下一个编号最小的描述符),因此检查将有意义。< / p>

答案 3 :(得分:0)

这个程序将在父进程中运行cat,并在子进程中运行tr,并且它希望通过tr读取cat的输出。

一开始,它打开一个管道,父级将写入fd [1],子级将从fd [0]读取,以便父级可以将数据写入子级。

在父母中,它将fd [1]复制到stdin;在孩子身上,它将fd [0]复制到stdin。

在child中,execlp运行tr,tr将从stdin读取,并且因为stdin已经被复制为fd [0],所以它实际上读取了cat从管道输出的内容。

execlp()在当前进程中运行新的可执行文件。您可以man execlp查询其详细信息。