从管道作为标准输入读取时出现“错误的文件描述符”错误

Rob*_*y75 5 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);
}
Run Code Online (Sandbox Code Playgroud)

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

这在几乎所有情况下都非常有效。该命令read()从其标准输入读取(使用)并获取由另一个进程写入管道的数据。

但有时该命令无法从其 stdin 流中读取,并在尝试这样做时收到“错误的文件描述符”错误。

什么可能导致此错误?

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

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

    dup2(pipe_in, 0);
    dup2(pipe_out, 1);
Run Code Online (Sandbox Code Playgroud)

我将对此进行几天的测试,因为错误很少出现。

Giu*_*ini 5

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

请看这里:

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

“将 freopen(3) 应用于这些流之一可以更改与流关联的文件描述符编号”

execl 之后,子进程只期望文件描述符 0 和 1 是标准输入和输出,但可能会发生 freopen 关闭 fd 0 并将另一个 fd 连接到 (FILE*)stdin。我建议您使用“open”、“close”、“dup”等系统调用并直接处理文件描述符 0 和 1(或者更好的是标准宏 STDIN_FILENO 和 STDOUT_FILENO)。