2016-02-12 92 views
0

我見過很多類似的問題,但都是針對特定案例,並沒有幫助我找到解決方案。我將不勝感激對我的情況的任何反饋,如下所示:爲什麼我不能寫入或讀取管道?

我想寫一個程序從文本文件中獲取字符數。該程序通過分派四個映射器和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; 
} 

我遇到的問題是,我不能寫減速管道。每當我嘗試寫入,讀取或關閉它們時,都會收到錯誤的地址錯誤。他們是否過期了?我沒有正確創建它們嗎? 如果有人有意見,我將不勝感激。

快速編輯:我刪除了所有的「close」語句,因爲它們有相同的問題。然而,我已經嘗試關閉它們應該關閉的管道,只是爲了找到相同的錯誤信息。

+1

您正在使用大錘來破解堅果 - http://dictionary.cambridge.org/us/dictionary/english/a-sledgehammer-to-crack-a-nut - 爲什麼? –

+2

總是,*總是*檢查錯誤!並閱讀手冊頁,例如[這個'寫'手冊頁](http://man7.org/linux/man-pages/man2/write.2.html)。 –

+0

@EdHeal這是一個演示mapper/reducer範例的類作業。完全沒有必要,但我需要弄明白。 – Haley

回答

0

你不顯示你的check_errors函數是什麼,但我猜想它只是打印一個錯誤消息,而沒有真正檢查錯誤,假設你只是在錯誤後調用它。所以你可能實際上沒有收到錯誤。

實際上你需要檢查你讀的返回值,並寫入招標信息中是否有錯誤發生:

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

注意,返回值也告訴你該消息的接收長度,如果有ISN」 (錯誤代碼MSGSIZE

1

「錯誤的地址」(errno == EFAULT)意味着你已經傳遞了一個無效的指向系統調用的指針,它本質上等價於段錯誤(我相信有些系統實際上只是提高SIGSEGV在這種情況下)。

看這句話:

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

這裏ccount是int類型。將int投射到指針始終是可疑的。

在上一行中,您將ccount指定爲返回值count_char()。現在你沒有向我們展示該函數的代碼,但是我猜測它會返回一個字符數 - 很可能是一個小整數。假設它返回17.你告訴write寫入位於地址17的MSGSIZE字節。這肯定不是你想要的。

如果你想該整數發送到減速機,以二進制格式,你可能想說

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

當然,你必須對減速裝置側的匹配代碼。


其他人已經在你的代碼解決了一些其他問題,如事實,你不能可靠地只是看errno(這大概是什麼check_errors那樣)檢測錯誤。如果系統調用沒有錯誤,則不會改變errno,即使它以前具有非零值。你應該做的是從write()檢查返回值;如果它是-1那麼發生了一個錯誤,然後你應該看看errno(或致電perror)看看它是什麼。

基本上,任何時候你進行系統調用並且不檢查返回值,你都有一個bug。

相關問題