2016-05-22 8 views
4

Ich habe diese Aufgabe, wo ich zwei Kinder mit Gabel erstellen muss. Der Elternteil muss diesen Kindern einige Briefe schicken und eine Nummer zurück erhalten. Die Kommunikation muss über Rohrleitungen erfolgen. Was ich nicht herausfinden kann, ist, warum mein Code es schafft, die Briefe an die Kinder zu schicken, aber dann einfach nichts tut. Zuerst dachte ich, dass es wegen der waitpid() Anrufe war, aber es scheint nicht der Fall zu sein. Was mich verblüfft ist, dass alles andere wie erwartet funktioniert, wenn ich in einem der Kindprozesse aufhöre und nur eine Zufallszahl sende.Wie sende ich Daten in C von zwei Kindern an Eltern mit Pipes?

#include <unistd.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <errno.h> 
#include <sys/wait.h> 
#include <stdlib.h> 
#include <string.h> 

#define PIPE_1 0 // write to 1st child 
#define PIPE_2 1 // write to parent from 1st child 
#define PIPE_3 2 // write to 2nd child 
#define PIPE_4 3 // write to parent from 2nd child 

int main() 
{ 
    pid_t p1, p2; 
    int pipes[4][2]; 
    FILE *read[4], *write[4]; 

    int k; 
    for (k = 0; k < 4; k++){ 
     if (-1 == pipe(pipes[k])){ 
      perror("Error creating pipe"); 
      exit(k+1); 
     } 
     read[k] = fdopen(pipes[k][0], "r"); 
     write[k] = fdopen(pipes[k][1], "w"); 
    } 

    if (-1 == (p1 = fork())){ 
     perror("Error, failed to fork first child"); 
     exit(5); 
    } 

    if (p1 == 0){ 
     // 1st child 
     fclose(write[PIPE_1]); 
     int caseChange = 0; 
     char c; 
     while(fscanf(read[PIPE_1], "%c", &c) != EOF){ 
      if (c >= 97 && c <= 122){ 
        c -= 32; 
        caseChange++; 
      } 
      printf("[Process (%d)]: %c\n", getpid(), c); 
     } 
     fclose(read[PIPE_1]); 

     fclose(read[PIPE_2]); 
     fprintf(write[PIPE_2],"%d",caseChange); 
     fflush(write[PIPE_2]); 
     fclose(write[PIPE_2]); 
    } 
    else{ 
     if (-1 == (p2 = fork())){ 
      perror("Error, failed to fork second child"); 
      exit(6); 
     } 

     if (p2 == 0){ 
      // 2nd child 
      fclose(write[PIPE_3]); 
      int caseChange = 0; 
      char c; 
      while(fscanf(read[PIPE_3], "%c", &c) != EOF){ 
       if (c >= 97 && c <= 122){ 
        c -= 32; 
        caseChange++; 
       } 
       printf("[Process (%d)]: %c\n", getpid(), c); 
      } 
      fclose(read[PIPE_3]); 

      fclose(read[PIPE_4]); 
      fprintf(write[PIPE_4],"%d",caseChange); 
      fflush(write[PIPE_4]); 
      fclose(write[PIPE_4]); 
     } 
     else{ 
      // Parent 
      //char *string = (char*) malloc(100); 
      char string[100]; 
      scanf("%s", string); 
      int i; 

      int readCaseChange, caseChange = 0; 

      fclose(read[PIPE_1]); 
      for (i = 0; i < strlen(string); i+=2){ 
       fprintf(write[PIPE_1],"%c",string[i]); 
       fflush(write[PIPE_1]); 
      } 
      fclose(write[PIPE_1]); 

      fclose(read[PIPE_3]); 
      for (i = 1; i < strlen(string); i+=2){ 
       fprintf(write[PIPE_3],"%c",string[i]); 
       fflush(write[PIPE_3]); 
      } 
      fclose(write[PIPE_3]); 

      waitpid(p1, NULL, 0); 
      fclose(write[PIPE_2]); 
      fscanf(read[PIPE_2], "%d", &readCaseChange); 
      fclose(read[PIPE_2]); 
      caseChange += readCaseChange; 

      waitpid(p2, NULL, 0); 
      fclose(write[PIPE_4]); 
      fscanf(read[PIPE_4], "%d", &readCaseChange); 
      fclose(read[PIPE_4]); 
      caseChange += readCaseChange; 

      printf("%d\n", caseChange); 
      fflush(stdout); 
     } 
    } 
    return 0; 
} 

Antwort

1

Sie wollen etwas schließen, die Sie nicht in jedem Kind mit, vor allem der Schreib-Seite für den übergeordneten Prozess:

// 1st child 
fclose(write[PIPE_1]); 
fclose(write[PIPE_3]); 

// 2nd child 
fclose(write[PIPE_1]); 
fclose(write[PIPE_3]); 

Andernfalls werden die Child-Prozesse die Schreib-Seite offen halten und Verhindern Sie, dass sich die Pipes vollständig schließen und dass Sie dort nie einen EOF in den Child-Prozessen erhalten. Sie haben dies teilweise getan, aber seit das 2. Kind [PIPE_1] geöffnet hatte, wurde PIPE_1 nie vollständig geschlossen.