c - 厕所 : standard input: Bad file descriptor on fork + pipe + execlp

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

可能是什么问题?

最佳答案

你有:

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();您的代码将管道的写入端复制到 child 的标准输入,这不是幸福的秘诀。修改后的代码将管道的读取端复制到 child 的标准输入。很容易记住哪个是哪个:stdin 是文件描述符 0 和管道描述符 0 是输入描述符(管道的读取端),而 stdout 是文件描述符 1 和管道描述符 1 是输出描述符(写管道的末端)。

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

wc 试图从一个只为写入而打开的文件描述符中读取时,会出现错误。

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

关于c - 厕所 : standard input: Bad file descriptor on fork + pipe + execlp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37603297/

相关文章:

c++ - 如何使用 DP 用 n 种不同的颜色绘制 r x r 字段,而不在同一行使用相同的颜色

c - 在 c 程序中使用 ffmpeg header

c - 使用交替的最小值和最大值对数组进行排序

linux - Dash,文件路径是否有任何限制

java - Linux 中的 UTF-8 问题

linux - 如何在基于 Unity 的 Linux 构建中设置默认命令行参数

c++ - 使用 libvlc 在 RTSP Streaming 中仅显示第一帧

linux - 如何跟踪在特定核心上运行的 PID 列表?

linux - 如何使用 grep 和 awk 提取特定值?

c - 在 C 中同步查询 SQLite 数据库