2012-05-24 3 views
0

Я занят заданием, но я застрял. Я получаю ошибки, и я не понимаю, что я делаю неправильно.Ошибка инициализации канала C

Итак, в основном я делаю троих детей. Между первым и вторым у меня есть труба (pipe12). Между вторым и третьим у меня есть труба (pipe23). Теперь, когда первый ребенок() готов с чтением, он закрывает pipe12, но чтение второго ребенка не получает EOF. Во-вторых, когда второй ребенок хочет писать до pipe23, ребенок падает.

Я думаю, что я делаю что-то неправильно при инициализации труб, но что?

Это родительский

for(childnr=2; childnr>=0;childnr--) 
{ 
    tasks[childnr].pid=fork(); 
    if(tasks[childnr].pid==-1) 
    { 
     printf("fork error\n"); 
     exit(1); 
    } 
    else if(tasks[childnr].pid==0) 
    { 
     switch(childnr) 
     { 
      case 0: 
       close(pipe12[0]); 
       close(pipe23[0]); 
       close(pipe23[1]); 
       reader(); 
       break; 
      case 1: 
       close(pipe12[1]); 
       close(pipe23[0]); 
       tokenizer(); 
       break; 
      case 2: 
       close(pipe12[0]); 
       close(pipe12[1]); 
       close(pipe23[1]); 
       evaluator(); 
       break; 
      default: 
       printf("childnr error\n");      //errorhandling 
     }   
    } 
    else 
     close(tasks[childnr].errorpipe[1]); 
} 
close(pipe12[0]); 
close(pipe12[1]); 
close(pipe23[0]); 
close(pipe23[1]); 
... continue with the parent 

Это первый ребенок:

void reader(void) 
{ 
    atexit(*reader_exit); 
    if((readfile = fopen(calculatorfile,"r"))==NULL) 
    { 
     printf("R send error to errorHandler");  //errpipe! 
     exit(0); 
    } 
    char line[50]; 
    const char *valid_characters = "-/*\n"; 
    while(fgets (line, sizeof line, readfile) != NULL) 
    { 
     printf("R reading ...%s",line); 
     char *c = line; 
     while(*c) 
     { 
      if(!strchr(valid_characters,*c)) 
      { 
       printf("R invalid character: %c in %s",*c,line); 
       line[0]=0; 
       break; 
      } 
      c++; 
     } 
     write(pipe12[1],line,sizeof line); 
    } 
    exit(0); 
} 

void reader_exit(void) 
{ 
    printf("R reader exit\n"); 
    fclose(readfile); 
    close(pipe12[1]); 
    close(tasks[childnr].errorpipe[1]); 
} 

И второй ребенок:

void tokenizer(void) 
{ 
    atexit(*tokenizer_exit); 
    char buffer[50]; 
    while(read(pipe12[0],buffer,sizeof buffer)!=EOF) 
    { 
     printf("T %s",buffer); 
     char *token = strtok(buffer," "); 
     while(token!=NULL) 
     { 
      printf("T %s\n",token); 
      write(pipe23[1],token,sizeof token); 
      token = strtok(NULL, " "); 
     } 
     sleep(2); 
    } 
    exit(0); 
} 
+0

Вы можете улучшить общность вашего читателя, передав ему дескриптор файла: 'reader (pipe12 [1])'. Аналогично токенизатору: 'tokenizer (pipe12 [0], pipe23 [1]);' и оценщик: 'оценщик (pipe23 [0]);'. Для читателя вы также должны передать имя файла: 'reader (calculatorfile, pipe12 [1]);'. –

+0

Спасибо, я сделаю это. – Kat

+0

Как ребенок терпит крах? 'SIGPIPE' или' SIGSEGV'/'SIGBUS'? – C2H5OH

ответ

1

Ваша основная проблема заключается в том, что read() возвращает 0 EOF , а не -1 или EOF.

Ваш код должен иметь петлю, как:

while (read(pipe12[0], buffer, sizeof buffer) > 0) 

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

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

reader(pipe12[1]) 
tokenizer(pipe12[0], pipe23[1]); 
evaluator(pipe23[0]); 

Для читателя, вероятно, вы должны передать имя файла тоже:

reader(calculatorfile, pipe12[1]); 

Этот код просто о работах:

#include <stdio.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <stdlib.h>  /* atexit() */ 
#include <string.h> 

static int pipe12[2]; 
static int pipe23[2]; 

struct task 
{ 
    pid_t pid; 
}; 
static struct task tasks[5]; 

static void evaluator(int i_fd); 
static void tokenizer(int i_fd, int o_fd); 
static void reader(char const *file, int o_fd); 

int main(void) 
{ 
    pipe(pipe12); 
    pipe(pipe23); 
    for (int childnr=2; childnr>=0;childnr--) 
    { 
     tasks[childnr].pid=fork(); 
     if (tasks[childnr].pid==-1) 
     { 
      printf("fork error\n"); 
      exit(1); 
     } 
     else if (tasks[childnr].pid==0) 
     { 
      switch (childnr) 
      { 
       case 0: 
        close(pipe12[0]); 
        close(pipe23[0]); 
        close(pipe23[1]); 
        reader("data-file", pipe12[1]); 
        break; 
       case 1: 
        close(pipe12[1]); 
        close(pipe23[0]); 
        tokenizer(pipe12[0], pipe23[1]); 
        break; 
       case 2: 
        close(pipe12[0]); 
        close(pipe12[1]); 
        close(pipe23[1]); 
        evaluator(pipe23[0]); 
        break; 
       default: 
        printf("childnr error\n");      //errorhandling 
        break; 
      }   
     } 
    } 
    close(pipe12[0]); 
    close(pipe12[1]); 
    close(pipe23[0]); 
    close(pipe23[1]); 

    printf("Parent waiting...\n"); 
    while (wait(0) != -1) 
     ; 
    printf("Brats are all dead!\n"); 
    return(0); 
} 

static void reader(char const *file, int o_fd) 
{ 
    FILE *fp; 
    if ((fp = fopen(file, "r"))==NULL) 
    { 
     printf("R send error to errorHandler");  //errpipe! 
     exit(0); 
    } 
    char line[50]; 
    const char *valid_characters = "-/*\n"; 
    while (fgets(line, sizeof(line), fp) != NULL) 
    { 
     printf("RI %s", line); 
     char *c = line; 
     while (*c) 
     { 
      if (!strchr(valid_characters, *c)) 
      { 
       printf("R invalid character: %c in %s\n", *c, line); 
       line[0] = '\0'; 
       break; 
      } 
      c++; 
     } 
     if (line[0] != '\0') 
     { 
      printf("RO %s", line); 
      write(o_fd, line, strlen(line)); 
     } 
    } 
    close(o_fd); 
    fclose(fp); 
    printf("Reader exiting\n"); 
    exit(0); 
} 

static void tokenizer(int i_fd, int o_fd) 
{ 
    char buffer[50]; 
    int nbytes; 
    while ((nbytes = read(i_fd, buffer, sizeof(buffer))) > 0) 
    { 
     buffer[nbytes] = '\0'; 
     printf("TI %*s\n", nbytes, buffer); 
     char *token = strtok(buffer, " \n"); 
     while (token!=NULL) 
     { 
      printf("TO %s\n", token); 
      write(o_fd, token, strlen(token)); 
      token = strtok(NULL, " "); 
     } 
     sleep(2); 
    } 
    printf("Tokenizer exiting\n"); 
    exit(0); 
} 

static void evaluator(int i_fd) 
{ 
    char buffer[50]; 
    int nbytes; 
    while ((nbytes = read(i_fd, buffer, sizeof(buffer))) > 0) 
    { 
     printf("EI %*s\n", nbytes, buffer); 
     buffer[nbytes] = '\0'; 
     char *token = strtok(buffer, " "); 
     while (token!=NULL) 
     { 
      printf("EO %s\n", token); 
      token = strtok(NULL, " "); 
     } 
     sleep(2); 
    } 
    close(i_fd); 
    printf("Evaluator exiting\n"); 
    exit(0); 
} 

Учитывая файл данных, содержащий:

123 456 
123 + 234 * 547/987 - 1 

Один прогон программы производится:

Parent waiting... 
RI 123 456 
RO 123 456 
RI 123 + 234 * 547/987 - 1 
RO 123 + 234 * 547/987 - 1 
Reader exiting 
TI 123 456 

TO 123 
TO 456 

EI 123 
EO 123 
TI 123 + 234 * 547/987 - 1 
EI 456 

TO 123 
TO + 
TO 234 
TO * 

TO 547 
TO/
EO 456 

TO 987 
TO - 
TO 1 

EI 123+234*547/987-1 

EO 123+234*547/987-1 

Tokenizer exiting 
Evaluator exiting 
Brats are all dead! 

Обратите внимание, что данные, считываемые с read() должен быть явно оканчивающимся на нуль; данные, считанные с fgets(), нет. Также обратите внимание, как была создана базовая отладка; все входы эхом, все выходы в следующую программу также повторяются. Это облегчает (или, по крайней мере, проще) видеть, где могут быть проблемы. В крайних случаях лучше было бы написать stderr или до fflush() после каждого printf(). Есть много деталей, которые являются субоптимальными, например, используя printf() с помощью только одного строкового аргумента.Структура задач в этом коде избыточна. Аргументы труб могут быть локальными переменными в пересмотренном коде.

+0

Это решило проблему с прочитанной, которая не закончилась. Но программа по-прежнему падает с первого приказа в токенизаторе. – Kat

+0

Пример run показывает, что токенизатор не сбой и успешная запись в оценщик. Чем отличается код и код? –

+0

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

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