繁体   English   中英

为什么不能写入管道或从管道读取?

[英]Why can't I write to or read from pipes?

我已经看到了很多类似的问题,但是所有这些问题都针对特定的情况,因此没有帮助我找到解决方案。 对于我的情况,请提供以下反馈:

我正在尝试编写一个程序来从文本文件中获取字符数。 该程序通过派生四个映射器和26个reducer并为它们中的每个创建管道来工作。 父进程将输入分为四行,然后将其传递给每个映射器,该映射器计算其行中每个字符的数量。 然后,每个映射器将计数传递到适当的缩减器,后者对所有四个计数求和并打印结果。

以下是到目前为止的代码:

 int main(int argc, char *argv[])
{
  int i = 0;

  FILE *input = fopen("input.txt", "r");

  // Things for reading line-by-line: see getline reference on man7.org
  char *line = NULL;
  size_t len = 0;

  // Where we'll store the messages
  static char message[MSGSIZE];

  for(i = 0; i < NUMREDUCERS; i++)
    {
      pipe(reducer_pipes[i]);
    }

  for(i = 0; i < NUMMAPS; i++)
    {
      // Step 1: Create pipes for communication using the system call pipe()
      pipe(mapper_pipes[i]);

      // Step 2: Fork a number of mappers (4).
      if (fork() == 0)
    {
      // Don't want to close the write pipe yet
      // Child process: one of the mappers

      read(mapper_pipes[i][0], message, MSGSIZE); // Read from reading end
      char *msg = "Error reading from pipe";
      check_errors(msg);

      // Get char count and write to pipe
      int j = 0;
      int ccount = 0;
      for(j = 0; j < NUMREDUCERS; j++)
        {
          // Count up the number of chars
          ccount = count_char(message, (char) (j + 97), MSGSIZE);

          // Write to the appropriate reducer pipe
          write(reducer_pipes[j][1], (char *) ccount, MSGSIZE);
          msg = "error writing to reducer pipe";
          check_errors(msg);

        }

      exit(EXIT_SUCCESS);
    }
      else
    {
      getline(&line, &len, input);
      // Parent process

      write(mapper_pipes[i][1], line, (int) len);
      char *msg = "Error writing to pipe";
      check_errors(msg);
    }
    }

  return 0;
}

我遇到的问题是我无法写入减速器管道。 每当我尝试写入,读取或关闭它们时,我都会收到一个错误的地址错误。 他们以某种方式到期了吗? 我没有正确创建它们吗? 如果有人愿意提供意见,我将不胜感激。

快速编辑:我删除了所有“关闭”语句,因为它们都存在相同的问题。 但是,我尝试关闭应该关闭管道的位置,只是找到了相同的错误消息。

“地址errno == EFAULT ”( errno == EFAULT )表示您已将无效指针传递给系统调用。 从本质上讲,它相当于一个段错误(我相信某些系统实际上在这种情况下会提高SIGSEGV )。

看这行:

      write(reducer_pipes[j][1], (char *) ccount, MSGSIZE);

这里的ccount是int类型的。 将int转换为指针始终是可疑的。

在上一行中,您ccount分配给count_char()的返回值。 现在您没有向我们展示该函数的代码,但是我想它会返回一个字符数-最有可能是一个小整数。 假设它返回了17。您正在告诉write写入位于地址17的MSGSIZE字节。这肯定不是您想要的。

如果您想以二进制格式将该整数发送给reducer,您可能想说

write(reducer_pipes[j][1], &ccount, sizeof(ccount));

当然,您必须在减速器端具有匹配的代码。


其他人已经解决了代码中的许多其他问题,例如您仅通过查看errno就无法可靠地检测错误(这大概就是check_errors所做的事情)。 如果系统调用没有错误,则即使先前具有非零值,也不会errno 相反,您应该做的是检查write()的返回值; 如果它是-1那么将发生错误,只有这样,您才应该查看errno (或致电perror )以查看其含义。

基本上,每当您进行系统调用并且不检查返回值时,都会遇到错误。

您没有显示您的check_errors函数是什么,但是我猜想它只是在显示错误消息而没有实际检查错误的情况下,假设您仅在发生错误后才调用它。 因此,您实际上可能并没有收到错误消息。

您实际上需要检查读写调用的返回值,以查看是否发生错误:

if ((len = read(mapper_pipes[i][0], message, MSGSIZE)) < 0) // Read from reading end
    perror("Error reading from pipe");

请注意,如果没有错误,返回值还会告诉您接收到的消息的长度(您应该在查看该消息的后续代码中使用该值代替MSGSIZE

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM