wc:标准输入:fork + pipe + execlp上的错误文件描述符

时间:2016-06-02 22:42:36

标签: c linux

我知道这是一个简单的练习,但我遇到了麻烦。我试图模仿:

grep arg1 arg2 | wc -l

我收到以下错误:" wc:标准输入:执行"时文件描述符错误。这是我的代码:

int main(int argc, char *argv[])
{
    if (argc != 3) usage();
    int pd[2]; //Pipe descriptor
    pipe(pd);
    int pid = fork();
    if (pid < 0) perror("Something failed on trying to create a child process!\n");
    else if (pid == 0) { //Child
        dup2(pd[1], 0);
        close(pd[0]);
        close(pd[1]);
        execlp("wc", "wc", "-l", (char *)NULL);
    } else { //Parent
        dup2(pd[0], 1);
        close(pd[0]);
        close(pd[1]);
        execlp("grep", "grep", argv[1], argv[2], (char *)NULL);
    }
}

可能是什么问题?

2 个答案:

答案 0 :(得分:2)

你有:

else if (pid == 0) { //Child
    dup2(pd[1], 0);
    close(pd[0]);
    close(pd[1]);
    execlp("wc", "wc", "-l", (char *)NULL);
}

你需要:

else if (pid == 0) { //Child
    dup2(pd[0], 0); 
    close(pd[0]);
    close(pd[1]);
    execlp("wc", "wc", "-l", (char *)NULL);
    fprintf(stderr, "Failed to execute 'wc'\n");
    exit(1);
}

关键变化是dup2();你的代码将管道的写端复制到孩子的标准输入,这不是幸福的秘诀。修订后的代码将管道的读取结束复制到子项的标准输入。很容易记住哪个是:stdin是文件描述符0,并且该对的管道描述符0是输入描述符(读取管道的末尾),而stdout是文件描述符1,并且该对的管道描述符1是输出描述符(写下管道的末尾)。

您需要在“父”代码中进行相反的更改。

wc尝试从只能写入的文件描述符中读取时,会出现错误。

请注意,如果execlp() - 或exec*()函数系列的任何其他成员 - 返回,则失败。处理该错误非常重要,通常是通过报告标准错误和退出问题。在exec*()操作之后没有声明是很正确的。

答案 1 :(得分:0)

正如我所看到的,你试图复制“wc -l | grep某事”的终端命令。

问题是你没有向wc提供输入。 wc -l命令需要一个输入,它应该对其行进行计数。尝试类似:

execlp("wc", "wc", "-l", "somefile.txt", (char *)NULL);