grep :(标准输入):错误的文件描述符

时间:2014-03-03 05:58:27

标签: c linux unix fork pipe

我正在尝试将stdin更改为管道插座并将stdout更改为另一个文件并使用grep。我收到以下错误:

grep: (standard input): Bad file descriptor

我的代码是:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>

int main()
{
        pid_t childpid;
        int fds[2];
        int stat;
        int fd = open("temp", O_WRONLY | O_APPEND);
        int old_in = dup(STDIN_FILENO);
        int old_out = dup(STDOUT_FILENO);
        if ((childpid = fork()) != 0)
        {
                wait(&stat);
                close(fds[1]);
                dup2(fds[0], STDIN_FILENO);
                dup2(fd, STDOUT_FILENO);
                system("grep hello");
                dup2(old_in, STDIN_FILENO);
                dup2(old_out, STDOUT_FILENO);
                close(fds[0]);
                close(fd);
        }

        else if (childpid == 0)
        {
                close(fds[0]);
                write(fds[1], "hello how are you", 100);
                close(fds[1]);
                return 0;

        }

        else
        {
                fprintf(stderr, "ERROR:\n");
                exit(1);
        }
        return 0;
}

所以基本上我正在写一个字符串到管道的写入口,并使用管道的另一个出口(读取)作为grep的stdin,并将stdout输出到另一个文件。我从childpid中删除了返回,并尝试使用另一个文件作为stdin,但仍然得到相同的错误。

1 个答案:

答案 0 :(得分:4)

有多个问题!其中包括:

  • 您没有致电pipe(fds);,因此您没有管道。

  • 幼稚的代码(write(fds[1], "hello how are you", 100);

    • 您应该在该行的末尾添加换行符。
    • 您应该只写出字符串中的字符数,并且字符串中没有100个字符。
  • 家长代码(if ((childpid = fork()) != 0)之后的区块)

    • 您无需在system之后恢复文件描述符,因为您即将退出。
    • 您可以使用其中一个exec*()函数代替system()
    • 一般来说,你不应该等孩子退出;可能有太多数据被推入管道,以便孩子能够在父母读取任何内容之前完成。在这种情况下,应该没问题,但要注意。
    • 你不应该在额外的文件描述符打开(grepold_in)的情况下真正执行old_out,但是当你在{{1}之后不恢复时,它们会消失呼叫。
    • 您应该在复制system()之后(以及在运行fds[0]之前)关闭grep

工作代码

#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

int main(void)
{
    pid_t childpid;
    int fds[2];
    int fd = open("temp", O_WRONLY | O_APPEND);
    if (pipe(fds) != 0)
        return 1;
    if ((childpid = fork()) != 0)
    {
        close(fds[1]);
        dup2(fds[0], STDIN_FILENO);
        dup2(fd, STDOUT_FILENO);
        close(fds[0]);
        close(fd);
        execlp("grep", "grep", "hello", (char *)0);
        fprintf(stderr, "Failed to execute grep\n");
        return 1;
    }
    else if (childpid == 0)
    {
        const char data[] = "hello how are you\nvery well thanks\n";
        close(fds[0]);
        write(fds[1], data, sizeof(data)-1);
        close(fds[1]);
        return 0;
    }
    else
    {
        fprintf(stderr, "ERROR:\n");
        return 1;
    }
}