c - grep : (standard input): Bad file descriptor

标签 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 的标准输入,并将标准输出输出到另一个文件。我已经从 childpid 中删除了返回值,并尝试使用另一个文件作为标准输入,但仍然出现相同的错误。

最佳答案

有多个问题!其中:

  • 您没有调用 pipe(fds);,所以您没有管道。

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

    • 您应该在行尾包含一个换行符。
    • 您应该只写与字符串中一样多的字符,并且显示的字符串中没有 100 个字符。
  • 父代码(if ((childpid = fork()) != 0) 之后的代码块)

    • 您不需要在 system 之后恢复文件描述符,因为您即将退出。
    • 您可以使用 exec*() 函数之一代替 system()
    • 一般来说,你不应该等待 child 退出;可能有太多数据被插入管道,以至于 child 无法在 parent 读取任何内容之前完成。在这种情况下,应该没问题,但要小心。
    • 您不应该在打开额外文件描述符(old_inold_out)的情况下真正执行 grep,但是当您不这样做时它们就会消失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;
    }
}

关于c - grep : (standard input): Bad file descriptor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22139665/

相关文章:

shell - 需要有关 unix 脚本的帮助以从特定位置读取数据并使用查询中提取的数据

c - sysmalloc 的 malloc 错误

c - 在 Windows 中使用线程对 100 万个整数进行排序

arrays - 从 ini 文件中提取信息并添加到关联数组 (Bash)

c - 如何使用 fork() 与父进程和子进程求和

c - 是否可以在线程中使用退出?

linux - 在帮助选项中包含子参数以明智地执行?

c++ - 为 Unix 创建一个 makefile

c - 数组中的位图更改值

将 char 转换为 int [C]