简体   繁体   English

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

[英]wc: standard input: Bad file descriptor on fork + pipe + execlp

I know this is a simple exercise but I'm having troubles with it. 我知道这是一个简单的练习,但是我遇到了麻烦。 I'm trying to emulate: 我正在尝试模仿:

grep arg1 arg2 | wc -l

I'm getting the following error: "wc: standard input: Bad file descriptor when executing". 我收到以下错误:“ wc:标准输入:执行时文件描述符错误”。 This is my code: 这是我的代码:

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);
    }
}

What can be the problem? 可能是什么问题?

You have: 你有:

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

You need: 你需要:

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);
}

The crucial change is the dup2() ; 关键的更改是dup2() your code copies the write end of the pipe to the child's standard input , which is not a recipe for happiness. 您的代码会将管道的写入端复制到孩子的标准输入中,这不是幸福的秘诀。 The revised code copies the read end of the pipe to the child's standard input. 修改后的代码将管道的读取端复制到孩子的标准输入中。 It's easy enough to remember which is which: stdin is file descriptor 0 and pipe descriptor 0 of the pair is the input descriptor (read end of the pipe), while stdout is file descriptor 1 and pipe descriptor 1 of the pair is the output descriptor (write end of the pipe). 容易记住哪个是:stdin是文件描述符0,而该对中的管道描述符0是输入描述符(管道的读取端),而stdout是文件描述符1,而该对中的管道描述符1是输出描述符。 (写出管道的末端)。

You need the converse change in the 'parent' code. 您需要在“父代”代码中进行相反的更改。

The error arises when wc tries to read from a file descriptor that's only open for writing. wc尝试从仅开放用于写入的文件描述符中读取时,会出现此错误。

Note that if execlp() — or any other member of the exec*() family of functions — returns, it failed. 请注意,如果execlp()exec*()函数系列的任何其他成员返回,则它将失败。 It is important to deal with that error, usually by reporting a problem on standard error and exiting. 重要的是,通常通过报告有关标准错误的问题并退出来处理该错误。 It is seldom correct to have no statement after the exec*() operation. exec*()操作之后没有语句很少是正确的。

As I can see, you trying to replicate the terminal command of "wc -l | grep something something". 如我所见,您尝试复制终端命令“ wc -l | grep某些东西”。

The problem is that you are not providing input to wc. 问题是您没有向wc提供输入。 wc -l command requires an input for which it should count its lines. wc -l命令需要一个输入,它应该为其行数。 Try something like: 尝试类似:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM