2016-10-02 4 views
0

Ich würde diesen Befehl ls -al/| tr a-j A-J | tr k-z K-Z ausführen und ich würde drei Kinder aus Vater Prozess erstellen.Pipes zwischen drei Kindern

Ich weiß, dass ich habe zwei Rohre zu öffnen, lassen Vater für alle seine Kinder wartet (alle Leitungen zu schließen) und in den Kindern ich habe

  • schließen STDIN auf dem ersten Kind
  • schließen STDOUT auf dem ersten Rohr und STDIN auf dem zweiten Rohr, auf das zweite Kind
  • schließen STDOUT auf dem dritten Kind

Nun, dies ist mein Code. Wenn ich es mit nur zwei Kindern benutze, funktioniert es. Aber wenn ich versuche, es mit drei Kindern zu laufen, funktioniert es nicht.

// command is ls -al/| tr a-j A-J | tr k-z K-Z 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main(int argc, char **argv) { 
int fd1[2]; 
int fd2[2]; 
pid_t pid = 0; 

pipe(fd1); 
pipe(fd2); 

pid = fork(); 
if(pid == 0) { 
    close(fd1[0]); 
    dup2(fd1[1], 1); 
    close(fd1[1]); 

    execlp("ls", "ls", "-al", "/", NULL); 
} 

pid = fork(); 
if(pid == 0) { 
    close(fd1[1]); 
    dup2(fd1[0], 0); 
    close(fd1[0]); 

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

    execlp("tr", "tr", "a-j", "A-J", NULL); 
} 

pid = fork(); 
if(pid == 0) { 
    close(fd2[1]); 
    dup2(fd2[0], 0); 
    close(fd2[0]); 

    execlp("tr", "tr", "k-z", "K-Z", NULL); 
} 

close(fd1[0]); 
close(fd1[1]); 
close(fd2[0]); 
close(fd2[1]); 

while ((pid = wait(NULL)) != -1); 

exit(0); 
} 

Vielen Dank im Voraus.

+0

Sie schließen nie eines der Rohrenden im übergeordneten Element. Das Kind, das von der Pipe liest, wartet auf * all * schreibt die Enden der Pipe, um zu schließen, aber die Eltern halten immer noch ein Ende offen. Schließe es. –

+0

Ich schließe am Ende Rohre. Ich muss sie am Anfang schließen? –

+0

'tr' wird nicht beendet, bis alle Schreibenden der Pipe geschlossen sind. Wenn der Parent 'wa' '' '' '' '' zu beenden ist, muss er das Ende der Pipe schließen, bevor es wartet, oder die beiden Prozesse werden deadlocked. –

Antwort

0

Sie könnten pipe2() mit close_on_exec Flag verwenden. Der folgende Code funktioniert:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <fcntl.h> 

int main(int argc, char **argv) { 
    int fd1[2]; 
    int fd2[2]; 
    pid_t pid = 0; 

    pipe2(fd1,O_CLOEXEC); 
    pipe2(fd2,O_CLOEXEC); 

    pid = fork(); 
    if(pid == 0) { 
    dup2(fd1[1],1); 
    execlp("ls", "ls", "-al", "/", NULL); 
    } 

    pid = fork(); 
    if(pid == 0) { 
    dup2(fd1[0],0); 
    dup2(fd2[1],1); 
    execlp("tr", "tr", "a-j", "A-J", NULL); 
    } 

    pid = fork(); 
    if(pid == 0) { 
    dup2(fd2[0],0); 
    execlp("tr", "tr", "k-z", "K-Z", NULL); 
    } 

    close(fd1[0]); 
    close(fd1[1]); 
    close(fd2[0]); 
    close(fd2[1]); 

    while ((pid = wait(NULL)) != -1); 

    exit(0); 
} 

Es ist möglich, auch Rohr() Aufruf zu verwenden, aber Sie sollten darauf achten, Deskriptoren überall manuell zu schließen, das ist fehleranfällig (Sie gezeigt, dass durch dieses Problem Entsendung; -)):

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main(int argc, char **argv) { 
    int fd1[2]; 
    int fd2[2]; 
    pid_t pid = 0; 

    pipe(fd1); 
    pipe(fd2); 

    pid = fork(); 
    if(pid == 0) { 
    close(fd1[0]); 
    dup2(fd1[1], 1); 
    close(fd1[1]); 

    execlp("ls", "ls", "-al", "/", NULL); 
    } 

    pid = fork(); 
    if(pid == 0) { 
    close(fd1[1]); 
    dup2(fd1[0], 0); 
    close(fd1[0]); 

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

    execlp("tr", "tr", "a-j", "A-J", NULL); 
    } 

    pid = fork(); 
    if(pid == 0) { 
    close(fd1[0]); 
    close(fd1[1]); 
    close(fd2[1]); 
    dup2(fd2[0], 0); 
    close(fd2[0]); 

    execlp("tr", "tr", "k-z", "K-Z", NULL); 
    } 

    close(fd1[0]); 
    close(fd1[1]); 
    close(fd2[0]); 
    close(fd2[1]); 

    while ((pid = wait(NULL)) != -1); 
} 
+0

Es wäre hilfreich, einen Link zur entsprechenden man-Seite hinzuzufügen (z. B. ['pipe2()'] (http://man7.org/linux/man-pages/man2/pipe.2.html)). –

+0

Danke. Aber was, wenn ich nur 'pipe()' und nicht 'pipe2()' benutzen soll? –

+0

@FedericoCuozzo: Wenn Sie 'pipe()' anstelle von 'pipe2()' verwenden, müssen Sie die nicht verwendeten Pipedeskriptoren schließen, bevor Sie die untergeordneten Elemente ausführen. In der Praxis bedeutet das, dass Sie 'dup()' oder (wahrscheinlich) 'dup2()' verwenden, um Pipedeskriptoren auf Standardeingabe oder Standardausgabe zu duplizieren. Sie müssen _all_ der Dateideskriptoren aus den Pipes vor Ihnen schließen benutze 'execvp()' oder was auch immer. Beachten Sie, dass 'execlp()' von begrenztem Wert ist; Sie müssen die Anzahl der Argumente zum Zeitpunkt der Kompilierung kennen (eine obere Schranke) - 'execvp()' ist die allgemeinere Schnittstelle. Für Ihre unmittelbaren Zwecke ist 'execlp()' in Ordnung. –

Verwandte Themen