2016-02-12 69 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。

相关问题