【问题标题】:"Bad file descriptor" error when reading from pipe as stdin从管道作为标准输入读取时出现“错误的文件描述符”错误
【发布时间】:2014-01-22 16:54:19
【问题描述】:

我 fork 并设置这样的命令:

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 在进程分叉之前已创建并填充了数据。

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

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

什么可能导致这个错误?

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

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

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

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

【问题讨论】:

  • 您的“真实”代码是否通过针对NULL 测试函数返回值来检查freopen() 是否有错误?

标签: c pipe


【解决方案1】:

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

请看这里:

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

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

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

【讨论】:

  • 嗯,你如何将 freopen 转换为 open/close/dup 调用?
  • 只是不要翻译。您不需要修改标准流(即 FILE *)标准输入/标准输出。文件描述符很重要。这篇文章解释了如何做到这一点:stackoverflow.com/questions/9084099/…
  • 所以不是 freopen("/input_pipe","r",stdin);我使用 in_fd = open("/input_pipe", "r");和 dup2(in_fd, 0);对吗?
  • 是的,更准确地说:in=open("(input_pipe", O_RDONLY); dup2(in,0); close(in); (还添加错误检查等...)
  • 这里是另一篇文章:homepage.ntlworld.com/jonathan.deboynepollard/FGA/…(参见“重定向 POSIX 文件描述符”段落)
猜你喜欢
  • 2023-03-06
  • 2019-02-26
  • 1970-01-01
  • 2010-11-06
  • 2014-12-07
  • 1970-01-01
  • 2021-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多