簡體   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