2016-06-01 13 views
0

Um einen Shell-Befehl interpretor zu realisieren, versuche ich Pipes auszuführen. Um es zu tun, verwende ich eine rekursive Funktion, in der ich die Rohrfunktion und einige Umleitungen mit dup2 verwende. Hier ist mein Code:fork/pipe/close in einer rekursiven Funktion

void   test_recurs(pid_t pid, char **ae) 
{ 
    char *const arg[2] = {"/bin/ls", NULL}; 
    char *const arg2[3] = {"/bin/wc", NULL}; 
    static int limit = 0; 
    int   check; 
    int   fd[2]; 

    if (limit > 5) 
    return ; 
    if (pipe(fd) == -1) 
    { 
     printf("pipe failed\n"); 
     return ; 
    } 
    pid = fork(); 
    if(pid != 0) 
    { 
     printf("père %d\n",getpid()); 
     close(fd[0]); 
     dup2(fd[1], 1); 
     close(fd[1]); 
     if ((execve("/bin/ls", arg, ae)) == -1) 
     exit(125); 
     dprintf(2, "execution ls\n"); 
     wait(&check); 
    } 
    else 
    { 
     printf("fils %d\n", getpid()); 
     close(fd[1]); 
     dup2(fd[0], 0); 
     close(fd[0]); 
     if ((execve("/bin/wc", arg2, ae)) == -1) 
     printf("echec execve\n");; 
     dprintf(2, "limit[%d]\n", limit); 
     limit++; 
     test_recurs(pid, ae); 
    } 
} 

Das Problem ist, es nur „ls | wc“ ausführen eine Zeit und dann auf der Standardeingabe warten. Ich weiß, dass das Problem von den Pipes (und den Umleitungen) kommen kann.

+1

'execve' wird nie zurückkehren. (Nun, ok, es wird zurückkehren, wenn es nicht funktioniert hat.) – user3386109

+0

Es gibt -1 zurück, wenn es nicht funktioniert ja ... – Roozaay

Antwort

2

Es ist ein wenig unklar, wie Sie versuchen, die Funktion, die Sie präsentieren, zu verwenden, aber hier sind einige bemerkenswerte Punkte darüber:

  • Es ist schlechte Form auf einer statischen Variablen verlassen Rekursionstiefe zu begrenzen, weil es nicht threadsicher und weil Sie zusätzliche Arbeit benötigen, um es zu verwalten (zum Beispiel um sicherzustellen, dass alle Änderungen zurückgesetzt werden, wenn die Funktion zurückkehrt). Verwenden Sie stattdessen einen Funktionsparameter.

  • Wie in Kommentaren beobachtet wurde, kehren die Funktionen der exec-Familie nur bei einem Fehler zurück. Obwohl Sie das bestätigen, bin ich mir nicht sicher, ob Sie die Konsequenzen zu schätzen wissen, denn beide Zweige Ihres Forks enthalten Code, der nie ausgeführt wird. Der rekursive Aufruf ist insbesondere tot und wird nie ausgeführt. Der Prozess, in dem die Funktion aufgerufen wird, führt einen execve() Aufruf selbst durch. Der Grund dafür, dass die Funktion nicht zurückkehrt, ist, dass sie das Prozessabbild durch das des neuen Prozesses ersetzt. Das bedeutet, dass die Funktion test_recurs()auch nicht zurückgibt.

Wie Schale gewöhnlich Gabel müssen/exec einen einzigen externen Befehl zu starten, muss sie normalerweise fork/exec für jeden Befehl in einer Pipeline. Wenn dies nicht der Fall ist, wird es nicht mehr ausgeführt - was auch immer ausgeführt wurde, ohne dass stattdessen Forks ausgeführt wurden.

Das Problem ist es nur "ls | wc" einmal ausführen und dann auf die Standardeingabe warten.

Sicherlich rekuriert es nicht, weil der rekursive Aufruf in einem Abschnitt des toten Codes ist. Ich vermute, du irrst dich in deiner Behauptung, dass es danach auf Standardeingabe wartet, weil der Prozess, der diese Funktion aufruft, /bin/ls ausführt, die nicht von der Standardeingabe liest. Wenn die ls beendet wird, aber Sie weder Shell noch ls hinterlassen, scheint das, was Sie dann sehen, auf stdin zu warten.

+0

Danke! Ich sehe wie es funktioniert :) – Roozaay

Verwandte Themen