2016-03-25 9 views
2

ich dieses Szenario zu realisieren versuchen:Programm will noch Eingang nehmen, selbst wenn die alle Leitungen geschlossen sind

fork and pipe scenario

wo zwei parallele Prozesse zu tr /a-z/ /A-Z/ geleitet werden und schließlich tr /a-z/ /A-Z/ Prozess wird an stdout verbunden.

ich dieses Programm geschrieben habe, um zu versuchen, um mein Ziel zu erreichen:

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

int main() 
{ 
    int dummy; 
    int fd[2]; 
    int i; 
    char* lsargs[] = {"/bin/ls", "-l", NULL}; 
    char* lsargs2[] = {"cat", "/etc/group", NULL}; 
    char* lsargs3[] = {"tr", "/a-z/", "/A-Z/", NULL}; 
    char** am[] = {lsargs, lsargs2, lsargs3}; 

    pipe(fd); 

    for (i = 0 ; i < 3 ; i++) 
    { 
     pid_t pid = fork(); 

     if (pid == 0) 
     { 
      if (i != 2) // ls -l & cat 
      { 
       // 0 -> stdin, 1 -> pipe write end 
       close(fd[0]); 
       dup2(fd[1], 1); 
       close(fd[1]); 
       execvp(am[i][0], am[i]); 
      } 
      else //TR AZ AZ 
      { 
       // 0 -> pipe read end 1 -> stdout 
       close(fd[1]); 
       dup2(fd[0],0); 
       close(fd[0]); 
       execvp(am[i][0], am[i]); 
      } 
      break; 
     } 
     else{ 
      wait(&dummy); 
     } 
    } 

    return 0; 
} 

ich die richtige Ausgabe aber mein Programm nicht beendet, sie will immer noch Eingang nehmen. Kannst du mir bitte helfen, den Grund zu verstehen?

+1

Sie warten nach Abzweigung des ersten Prozesses. Ihre Schleife ist zu schlau, ich schlage vor, Sie würden die Schleife ausrollen –

+0

@AnttiHaapala was würden Sie vorschlagen? Ich weiß, dass die Verwendung einer Schleife bedeutungslos ist, ich habe sie für einen speziellen Zweck verwendet. –

+1

Anstelle von 'for' schreiben Sie den Code so, dass er sich wiederholt; dann kannst du erkennen, welcher Teil wiederholt werden kann und warum. Nun wird Ihr Elternteil warten, bis das erste Kind * austritt * bevor * das nächste Kind sogar gegabelt, execed wird oder seine Leitung läuft. –

Antwort

1

Der Prozess der obersten Ebene schließt das Rohr nicht. Da der Elternprozess wirklich nur ein Koordinator ist und die Pipe nicht wirklich verwendet, muss er beide Enden schließen, sobald der letzte fork Aufruf erfolgt ist. Eine Möglichkeit, dies zu tun, besteht darin, den Schließungscode in den Fall else einzufügen. Zum Beispiel:

else { 

    /* ADDED CODE - close the pipes after last fork */ 
    if (i == 2) { 
     close(fd[0]); 
     close(fd[1]); 
    } 

    wait(&dummy); 
} 
+0

Code funktioniert so, wie ich es will, aber Antti Haapalas Kommentar im Hauptpost lässt mich fragen: Benütze ich wait (& dummy) angemessen? Wenn nicht, wie kann ich es entsprechend verwenden? –

+1

@ ArdaGüney Nun, es hängt davon ab, was Ihr gewünschtes Verhalten ist. Ihr aktuelles Warteverhalten ist korrekt, wenn Sie möchten, dass die Ausgaben "ls" und "cat" nacheinander sequenziert werden. Wenn Sie nicht nach dem ersten "fork" warten, dann werden die 'ls'- und' cat'-Ausgaben wahrscheinlich verschachtelt ausgegeben, da beide versuchen, gleichzeitig in die 'pipe' zu ​​schreiben, und es wird daher unbestimmt sein Die Reihenfolge der Ausgabe wird sein. – kaylum

+0

Ich kann nicht herausfinden, wie man keine Zombies zurücklässt und ls & cat gleichzeitig laufen lässt. Das Hinzufügen einer 'if (i! = 0)' Anweisung zum Warten (& dummy) funktioniert nicht. –

Verwandte Themen