从管道读取stdin时出现“错误的文件描述符”错误

时间:2014-01-22 16:54:19

标签: c pipe

我分叉并设置如下命令:

pid_t pid;
pid = fork();
if (pid == 0)
{   // I am the child
    freopen("/input_pipe","r",stdin);
    freopen("/output_pip","w",stdout);
    execl("/bin/sh", "sh", "-c", command, (char *)NULL); // using execv is probably faster
    // Should never get here
    perror("execl");
    exit(1);
}

在分叉进程之前,已经创建了/ input_pipe并填充了数据。

这在几乎所有情况下都适用。该命令从其stdin读取(带有read())并获取由另一个进程写入管道的数据。

但有时命令无法从其stdin流中读取并在尝试时出现“Bad file descriptor”错误。

什么可能导致此错误?

编辑:我已将freopen部分更改为:

    pipe_in = open(pipename_in, O_RDONLY);
    pipe_out = open(pipename_out, O_WRONLY);

    dup2(pipe_in, 0);
    dup2(pipe_out, 1);

我会测试这几天,因为错误只是很少出现。

1 个答案:

答案 0 :(得分:4)

问题的一个可能来源是" stdin" " stdout"不必分别对应文件描述符0和1。在运行时库的许多实现中,freopen可以更改属于FILE *的文件描述符。文件描述符属于内核,而FILE属于运行时库,它们不一定是对齐的。

请看这里:

http://man7.org/linux/man-pages/man3/stdout.3.html

"将freopen(3)应用于其中一个流可以更改与流关联的文件描述符编号"

在execl之后,子进程只期望文件描述符0和1是标准输入和输出,但是可能发生freopen关闭fd 0并且连接另一个fd到(FILE *)stdin。 我建议你使用"打开","关闭"," dup" etc ...系统调用并直接处理文件描述符0和1(或者更好的是,标准宏STDIN_FILENO和STDOUT_FILENO)。