2016-04-27 17 views
1

Ich muss ein solches IPC-Schema implementieren:Multi-Pipe funktioniert nicht

runtime data -> filter1 -> filter2 -> output. (wie data | filter1 | filter2).

Ich kann Daten an den ersten Filter übergeben, aber an zweiter Stelle kann ich nicht (vielleicht weil im ersten Kind stdout fd nicht geschlossen ist). Wie man ein solches Schema richtig implementiert?

P.S. filter1 und filter2 lesen einfach von stdin und schreiben nach stdout.

Mein Code:

int main() { 
    int fd1[2]; 
    pipe(fd1); 
    pid_t pid1; 

    if ((pid1 = fork()) > 0) { 
     char data[] = "Hello world!"; 

     close(fd1[0]); 
     write(fd1[1], data, sizeof(data)); 
     close(fd1[1]); 
     wait(NULL); 
     exit(EXIT_SUCCESS); 

    } else if (pid1 == 0) { 
     int fd2[2]; 
     pipe(fd2); 
     pid_t pid2; 

     dup2(fd1[0], STDIN_FILENO); 
     dup2(fd2[1], STDOUT_FILENO); 
     close(fd1[0]); close(fd1[1]); 
     close(fd2[0]); close(fd2[1]); 

     if ((pid2 = fork()) > 0) { 
      execl("./upcase", "upcase", NULL); 
      perror("execl"); 
      exit(EXIT_FAILURE); 
     } else if (pid2 == 0) { 
      close(fd1[0]); close(fd1[1]); 

      dup2(fd2[0], STDIN_FILENO); 
      close(fd2[0]); close(fd2[1]); 

      execl("./reverse", "reverse", NULL); 
      perror("execl"); 
      exit(EXIT_FAILURE); 
     } else { 
      perror("pid2"); 
      exit(EXIT_FAILURE); 
     } 

    } else { 
     perror("pid1"); 
     exit(EXIT_FAILURE); 
    } 

} 
+0

"* vielleicht, weil in der ersten Kind stdout fd nicht geschlossen ist *" - Es scheint, wie Sie das Problem bereits identifiziert haben. Da der erste Filter niemals EOF in seiner Eingangsleitung sieht (da er von einem anderen Prozess offengehalten wird), wird er niemals enden. – Dolda2000

+0

@ Dolda2000 Ja, aber wie kann ich stdout fd im äußeren Prozess schließen? – 0x1337

+0

Sie haben es bereits im übergeordneten Prozess geschlossen. Das Problem scheint eher zu sein, dass Sie es nicht in Ihrem "umgekehrten" Kind schließen. – Dolda2000

Antwort

1

Sie sind zu früh, um die Rohre zu schließen. In der Regel schließen Sie fd2[0], bevor Sie es in dup2 verwenden. Und wenn Sie FILENO_STDOUT vor dem zweiten Fork umleiten, hat der zweite Filter nicht mehr Zugriff auf das ursprüngliche Stdout.

folgende Code funktioniert:

int main() { 
    int fd1[2]; 
    pipe(fd1); 
    pid_t pid1; 

    if ((pid1 = fork()) > 0) { 
     char data[] = "Hello world!"; 

     close(fd1[0]); // OK, will no longer be used 
     write(fd1[1], data, sizeof(data)); 
     close(fd1[1]); 
     wait(NULL); 
     exit(EXIT_SUCCESS); 

    } else if (pid1 == 0) { 
     int fd2[2]; 
     pipe(fd2); 
     pid_t pid2; 
     close(fd1[1]); // OK, no used from here 

     if ((pid2 = fork()) > 0) { 
     dup2(fd1[0], STDIN_FILENO); // redirections for filter1 
     dup2(fd2[1], STDOUT_FILENO); 
     close(fd1[0]);    // close everything except stdin and stdout 
     close(fd2[0]); close(fd2[1]); 
      execl("./upcase", "upcase", NULL); 
      perror("execl upcase"); 
      exit(EXIT_FAILURE); 
     } else if (pid2 == 0) { 
      close(fd1[0]);    // not used here 

      dup2(fd2[0], STDIN_FILENO); // redirection for filter2 
      close(fd2[0]); close(fd2[1]); // close all what remains 

      execl("./reverse", "reverse", NULL); 
      perror("execl reverse"); 
      exit(EXIT_FAILURE); 
     } else { 
      ... 
Verwandte Themen