2016-02-12 4 views
0

Я видел много подобных вопросов, но все они касались конкретных случаев и не помогли мне найти решение. Я был бы признателен за любые отзывы о моей ситуации, которые выглядят следующим образом:Почему я не могу писать или читать из труб?

Я пытаюсь написать программу для получения символов из текстового файла. Программа работает путем разметки четырех карт и 26 редукторов и создания труб для каждого из них. Родительский процесс разделяет входные данные на четыре строки и передает один к каждому картографу, который подсчитывает количество каждого символа в его строке. Затем каждый преобразователь передает отсчеты на соответствующие редукторы, которые суммируют все четыре счета и печатают результат.

Ниже мой код до сих пор:

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; 
} 

Проблема я встречая, что я не могу написать к редуктору труб. Я получаю ошибку плохого адреса, когда я пытаюсь писать, читать или закрывать их. Они как-то истекли? Я не создал их правильно? Если у кого-нибудь есть предложения, я был бы очень признателен.

Быстрое редактирование: я удалил все мои «близкие» утверждения, поскольку у них была такая же проблема. Тем не менее, я пытался закрыть трубы, где они должны быть закрыты, только чтобы найти то же сообщение об ошибке.

+1

Вы используете кувалду, чтобы взломать орех - http://dictionary.cambridge.org/us/dictionary/english/a-sledgehammer-to-crack-a-nut - Почему? –

+2

Всегда, * всегда * проверяйте наличие ошибок! И читайте страницы руководства, например [эту страницу руководства 'write'] (http://man7.org/linux/man-pages/man2/write.2.html). –

+0

@EdHeal Это назначение класса для демонстрации парадигмы mapper/редуктора. Совершенно ненужно, но мне нужно понять это. – Haley

ответ

0

Вы не показываете, какая ваша функция check_errors есть, но я бы предположил, что она просто печатает сообщение об ошибке, фактически не проверяя ошибки, в предположении, что вы вызываете ее только после ошибки. Таким образом, вы не можете получить ошибку.

Вы должны фактически проверить возвращаемое значение вашего чтения и записи вызовов, чтобы увидеть, если произошла ошибка:

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

Обратите внимание, что возвращаемое значение также говорит вам длину полученного сообщения, если ISN» t ошибка (и вы должны использовать это вместо MSGSIZE в следующем коде, который смотрит на сообщение.

1

«Плохой адрес» (errno == EFAULT) означает, что вы передали неверный указатель на системный вызов. Это по сути эквивалент segfault (я считаю, что некоторые системы просто поднимают SIGSEGV в этой ситуации).

Посмотрите на этой линии:

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

Здесь ccount имеет тип междунар. Приведение int к указателю всегда является подозрительным.

В предыдущей строке вы присвоили ccount возвращаемому значению count_char(). Теперь вы не указали нам код для этой функции, но я собираюсь угадать, что он возвращает количество символов - скорее всего небольшое число. Скажем, он вернулся 17. Вы говорите write, чтобы написать MSGSIZE байт, которые расположены по адресу 17. Это, безусловно, не то, что вы хотите.

Если вы хотите отправить это целое число редуктора, в двоичном формате, вы, вероятно, хотел сказать

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

И, конечно, вы должны иметь соответствующий код на стороне редуктора.


Другие люди обратились ряд других вопросов, в вашем коде, например, тот факт, что вы не можете надежно обнаруживать ошибки, просто посмотрев на errno (которые, предположительно, является то, что check_errors делает). Если системный вызов не имеет ошибки, он оставляет errno нетронутым, даже если он имел ненулевое значение ранее. Вместо этого вы должны проверить возвращаемое значение от write(); если это -1, тогда произошла ошибка, и только тогда вы должны посмотреть на errno (или позвонить perror), чтобы узнать, что это было.

В принципе, в любое время, когда вы делаете системный вызов и не проверяете возвращаемое значение, у вас есть ошибка.

Смежные вопросы