2017-12-09 5 views
1

Ich versuche, etwas wie das in C mit Rohrleitungen und Gabel zu arbeiten: Echo "eine Operation wie 10 + 10" | bc2-Rohr, eine Gabel, BC und execlp (C)

Um genau zu sein, habe ich versucht, 2 Pipes zu erstellen, eine, wo der Server die Operation schreiben wird und BC liest und eine andere, wo das Ergebnis der Operation (von bc) gehen wird und der Server es lesen und printf es. Dazu ändere ich die Ausgabe und Eingabe des Eltern- und Kindprozesses.

Hier ist mein Code:

int main() {

int t1, t2; 
char resultat[5]; 
int pipe1[2]; 
int pipe2[2]; 

pipe(pipe1); 
pipe(pipe2); 


int resultat_fork = fork(); 

if(resultat_fork == -1){ 
    exit(EXIT_FAILURE); 
} 

if(resultat_fork!=0){ 
    printf("I am the parent\n"); 

    close(pipe1[0]); 
    close(pipe2[1]); 
    //We only want to write into pipe1 and read from pipe2, we can close the two other 

    write(pipe1[1], "20*5\n", 20); 
    //write on pipe1 the expression 

    read(pipe2[0], resultat, sizeof(resultat)); 
    //read from pipe2 the answer (written by bc) 

    printf("resultat : %s\n",resultat); 

    close(pipe1[1]); 
    close(pipe2[0]); 


}else{ 
    printf("I am the children\n"); 

    close(pipe1[1]); 
    close(pipe2[0]); 
    //We only want to write into pipe2 and read from pipe1, we can close the two other 

    dup2(pipe1[0], 0); 
    //redirection standard input to pipe1[0] 

    dup2(pipe2[1], 1); 
    //redirection standard output to pipe2[1] 

    execlp("bc", "bc", NULL); 
    //execute bc, which normaly will read the operation from pipe1 and write the answer into pipe2, but I think it's here the problem come out 

    close(pipe1[0]); 
    close(pipe2[1]); 
} 


return 0; 

}

ich die richtige Antwort zu bekommen, aber mit dem Fehler: „(standard_in) 2 : ungültiges Zeichen:^@ " " (standard_in) 2: unzulässiges Zeichen:: " plus ich muss STRG C drücken, um zu beenden. Ich denke, es kommt aus BC, aber warum ...

Was mache ich falsch? Vielen Dank! Ich habe schon einige Beispiele gesehen, aber nur eine Pfeife geworfen.

+0

Ihr Test für das Elternteil/Kind ist falsch. Wenn 'fork()' null zurückgibt, sind Sie im Kind. Andernfalls ist der zurückgegebene Wert die PID des Kindes, die im Wesentlichen nie den Wert 1 hat. –

+0

Beachten Sie, dass wenn Sie irgendwelche "Ich bin hier" -Nachrichten gedruckt hätten, Sie beide Prozesse gesehen hätten: "Ich bin kindisch" und weder sagen "Ich bin elterlich". –

+0

Vielen Dank für Ihre Antwort. Schade. Es tut mir wirklich leid. Jetzt bringt es mich immer wieder zurück "(standard_in) 1: unzulässiges Zeichen:^@".Ich glaube, es kommt von der dup2, die nicht richtig verwendet werden, aber ich bin mir nicht sicher – Karl

Antwort

1

Das funktioniert. Beachten Sie, wie die Größe der zu schreibenden Daten festgelegt wird und wie die Schreib- und Lesevorgänge überprüft und Dateideskriptoren geschlossen werden. (Denken Sie daran: sizeof("string literal") zählt der Null-Byte, im Gegensatz zu strlen() Es ist auch eine Kompilierung Zeitkonstante jedoch mehr Allzweck-Code strlen() auf dem aktuellen Ausdruck Zeichenfolge verwenden würde...)

Daumenregel: Wenn Sie dup2() verwenden, um Duplizieren Sie einen Pipe-Dateideskriptor mit Standardeingabe oder Standardausgabe, schließen Sie beide Enden der Pipe.

Das gilt auch, wenn Sie stattdessen dup() oder fcntl() mit F_DUPFD oder F_DUPFD_CLOEXEC verwenden.

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

int main(void) 
{ 
    char resultat[5]; 
    int pipe1[2]; 
    int pipe2[2]; 

    pipe(pipe1); 
    pipe(pipe2); 

    int resultat_fork = fork(); 

    if (resultat_fork == -1) 
    { 
     exit(EXIT_FAILURE); 
    } 

    if (resultat_fork != 0) 
    { 
     printf("I am the parent\n"); 

     close(pipe1[0]); 
     close(pipe2[1]); 

     if (write(pipe1[1], "20*5\n", sizeof("20*5\n") - 1) != sizeof("20*5\n") - 1) 
      fprintf(stderr, "write to child failed\n"); 

     int nbytes = read(pipe2[0], resultat, sizeof(resultat)); 
     if (nbytes <= 0) 
      fprintf(stderr, "read from child failed\n"); 
     else 
      printf("resultat: [%.*s]\n", nbytes, resultat); 

     close(pipe1[1]); 
     close(pipe2[0]); 
    } 
    else 
    { 
     printf("I am the child\n"); 

     close(pipe1[1]); 
     close(pipe2[0]); 
     dup2(pipe1[0], 0); 
     dup2(pipe2[1], 1); 
     close(pipe1[0]); /* More closes! */ 
     close(pipe2[1]); /* More closes! */ 

     execlp("bc", "bc", NULL); 
     fprintf(stderr, "Failed to execute bc\n"); 
     exit(EXIT_FAILURE); 
    } 

    return 0; 
} 

Es gibt immer noch Raum für die Verbesserung der Fehlerbehandlung; Der Code geht weiter, nachdem einige der Fehler gemeldet wurden, was wahrscheinlich nicht das beste Verhalten ist.

Ausgang:

I am the parent 
I am the child 
resultat: [100 
] 

(Anmerkung:.., Wenn Sie die Ausgabe des Programms Rohr irgendwo, Sie nicht die I am the child Meldung Aus den Gründen, warum finden printf() anomaly after fork())

+0

Vielen Dank. Ich kann den Code jetzt nicht testen, aber sobald ich kann, werde ich es versuchen und Ihnen antworten. – Karl