eof bedingung bei unbenannter pipe



  • Hey,
    ich habe folgendes Problem,
    ich habe 2 Prozesse, welche die selbe unbenannte pipe benutzen.
    im einen wird folgendes ausgeführt:

    while(fgets(eab, sizeof(eab), stdin)!=NULL)
      write(pipe1[1], eab, sizeof(eab));
    close(pipe1[1]);
    close(pipe1[0]);
    

    und im anderen:

    while(read(pipe1[0], eab, sizeof(eab))!=EOF)
          printf("%s\n", eab);
    

    klappt auch ganz gut,
    ich gebe einen buchstaben ein, drücke enter und dieser buchstabe wird vom anderen prozess ausgegeben.
    nur sobald ich strg-d drücke, gibts bei fgets ja NULL und die pipe wird geschlossen. das müsste im anderen Prozess doch die eof bedingung beim read auslösen..tuts aber nicht. der bleibt in der schleife hängen und wartet, dass was durch die pipe kommt, was er ausgeben kann.

    wo liegt mein Fehler?
    lg



  • man: read(2) gibt nicht EOF zurück.



  • Ach und wenn ich in Prozess 1 pipe1[0](0 ist ja für read da?!) close, kann ich im anderen Prozess immernoch lesen. Entspricht ein close(pipe[0]) in Prozess 1 einem close[pipe[1]) in prozess 2?

    Kann ich mir das bildlich so vorstellen, dass ich 2 Gartenschläuche habe:

    [0]-----------[1]
    [1]-----------[0]
    und bei einem close() praktisch 1 Ende verstopfe, sodass der komplette Schlauch nutzlos wird?

    (Ich brauch immer alles bildlich^^)
    lg



  • und wie erkenn ich dann, ob die Pipe zu ist?
    Im script steht:
    i=read(...)
    i>0 Anzahl der empfangenen Bytes
    i<0 Fehler
    i==EOF das Schließen der Pipe sorgt auf der Gegenseite für diese Bedingung



  • Jeder Childprozess hat seine eigenen Filedeskriptoren. Was in Prozess A passiert hat erstmal keine Auswirkungen auf auf Prozess B, d.h. close in A hat keine Wirkung in B.

    Ansonsten: http://beej.us/guide/bgipc/output/html/multipage/index.html



  • Mit Ctrl-D wird im Child-Prozess die Eingabe ueber stdin beendet.
    Die betreffende Pipe wird geschlossen und der Child-Prozess be-
    endet. Im Parent-Prozess ist entsprechend auf das Schliessen der
    Pipe zu reagieren, indem von dem betreffenden Child-Prozess keine
    Daten mehr angefordert werden.

    Aber wie soll ich nun mitbekommen, dass die pipe zu ist?



  • Hmm, naja laut FAQ sollte das genauso gehen. Aber da war irgendwas ...

    Ah, ja. Du testest auf EOF, aber read soll ja 0 zurueckgeben.

    On success, the number of bytes read is returned (zero indicates end of file)

    EOF ist nicht zwingend 0, sondern -1.



  • Hmm, die einen sagen

    Jeder Childprozess hat seine eigenen Filedeskriptoren. Was in Prozess A passiert hat erstmal keine Auswirkungen auf auf Prozess B, d.h. close in A hat keine Wirkung in B.

    jmd anderes

    Hmm, naja laut FAQ sollte das genauso gehen. Aber da war irgendwas ...

    Ah, ja. Du testest auf EOF, aber read soll ja 0 zurueckgeben.
    Zitat:
    On success, the number of bytes read is returned (zero indicates end of file)
    EOF ist nicht zwingend 0, sondern -1.

    ich poste jetzt mal meien kompletten quelltext:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    char eab[20];
      int p[2];
      int o[2];
    int main(void)
    {
    
      pid_t pid1, pid2;
      pipe(p);
      pipe(o);
      pid1=fork();
      switch(pid1){
        case 0: child1();
        break;
        default:
          pid2=fork();
          switch(pid2){
    	case 0: child2();
    	break;
    	default: parent();
    	break;
          }
          break;
      }
        return 0;
    }
    
    int child1(){
      while(fgets(eab, sizeof(eab), stdin)!=NULL)
      write(p[1], eab, sizeof(eab));
    close(p[1]);
    close(p[0]);
    
      return 0;
    }
    int child2(){
      return 0;
    }
    int parent(){
      while(read(p[0], eab, sizeof(eab))!=0)
          printf("%s\n", eab);
      return 0;
      wait(NULL);
      wait(NULL);
    }
    

    ich sitz jetzt schon seit heut früh und bekomm gleich nen kollaps.
    -.-
    wieso geht der nich aus der schleife raus wenn ich strg-d drücke?
    lg



  • Also ich würde dem lesenden PRozess vom sendenden Prozess her mitteilen,
    das game-over ist und er sich beenden kann - quasi so eine Ar
    spezielle info - wenn die der lesende kriegt, macht er close und tschüß.
    Der Sendende macht dann ebenfalls close und tschüß.
    Geht bestimmt einfacher und eleganter - aber für mich persönlich ist
    das so verständlicher
    ein strcmp(eingabe,"Feierabend") liest sich halt gut...



  • Teste mal bei while(read(p[0], eab, sizeof(eab))!=0) auf > 0.
    > 0 Anzahl der gelesenen Daten
    = 0 ist EOF
    < 0 ist Fehler.

    Eine zusammengebrochene Pipe kann auch ein Fehler sein.
    Das Lesen ist beendet bei EOF oder Fehler.



  • Dieser Thread wurde von Moderator/in rüdiger aus dem Forum C (C89 und C99) in das Forum Linux/Unix verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Die Sache ist folgende:
    Die EOF bedingung wird nur dann ausgelöst, wenn der andere Teil der Pipe bereits zu ist.
    Also habe ich vor die while schleife mit dem read drin einfach close(p[1]); geschrieben und schon sorgt ein close auf der anderen seite dafür, dass die komplette pipe dicht ist und die eof bedingung wird ausgelöst.
    folgendes funktioniert nun also:

    int child1(){
      close(p[0]);
      while(fgets(eab, sizeof(eab), stdin)!=NULL)
      write(p[1], eab, sizeof(eab));
    close(p[1]);
    
      return 0;
    }
    
    int parent(){
      close(p[1]);   //Ohne das Close hier gehts nicht!!!
      while(read(p[0], eab, sizeof(eab))!=0)
          printf("%s\n", eab);
      return 0;
      wait(NULL);
      wait(NULL);
    }
    

    Der Punkt ist nun aber, dass ich im parent Prozess ab und zu auf der Pipe schreiben muss, jedoch die EOF Bedingung trotzdem auslösbar bleiben muss, bedeutet also für mich ich muss nach dem schreiben p[1] schließen und vor dem schreiben wieder öffnen.
    doch wie bekomm ich eine pipe wieder geöffnet?
    wenn ich das mit pipe() mache, so funktioniert das doch nur wenn ich danach ein fork() benutze, oder?

    lg



  • Ich realisiere es jetzt mit 2 pipes pro child Prozess.
    Folgendes Problem habe ich aber immernoch:
    wenn ich nur einen Child Prozess verwende, klappt alles prima, nach strg-d wird beendet. habe ich 2 Child Prozesse klappt auf einmal garnichts mehr. woran liegt das?
    hier der quelltext mit 1 Child(Funktionsfähig):

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    char eab[20];
    char sig[10];
      int cp1[2];
      int cp2[2];
      int pc1[2];
      int pc2[2];
    
    int main(void)
    {
    
      pid_t pid1, pid2;
      pipe(pc1);
      pipe(pc2);
      pipe(cp1);
      pipe(cp2);
      pid1=fork();
      switch(pid1){
        case 0: child1();
        break;
        default:
          pid2=fork();
          switch(pid2){
    	case 0: child2();
    	break;
    	default: parent();
    	break;
          }
          break;
      }
        return 0;
    }
    
    int child1(){
      printf("1 gestartet\n");
      int stop=0;
       close(pc1[1]);
     close(cp1[0]);
      while(!stop){
        printf("1 warte auf startsignal\n");
        read(pc1[0], eab, sizeof(eab)); //warte auf startsignal
      printf("Child 1 Eingabe:\n");
     if(fgets(eab, sizeof(eab), stdin)==NULL)
       stop=1;
     else
    write(cp1[1], eab, sizeof(eab));
    
      }
      close(cp1[1]);
      printf("1 beendet\n");
      return 0;
    }
    
    int child2(){
    
      return 0;
    }
    int parent(){
      close(pc1[0]);
      close(cp1[1]);
      close(pc2[0]);
      close(cp2[1]);
      int stop1=0, stop2=0, stop=0;
      while(!stop){
    
        if(!stop1){
          printf("Parent Zweig 1\n");
          write(pc1[1], "sig\0", 5); //schreibe startsignal
          printf("warte auf eingabe\n");
        if(read(cp1[0], eab, sizeof(eab))==0){
          stop1=1;
        printf("EOF erhalten\n");
    
        }
        else
          printf("Ausgabe vom Child 1:%s\n", eab);
      }
      if(!stop2){
     stop2=1;
        }
    
      if(stop1&&stop2)
        stop=1;
      }
      wait(NULL);
      wait(NULL);
    return 0;
    }
    

    hier mit 2 childs:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    char eab[20];
    char sig[10];
      int cp1[2];
      int cp2[2];
      int pc1[2];
      int pc2[2];
    
    int main(void)
    {
    
      pid_t pid1, pid2;
      pipe(pc1);
      pipe(pc2);
      pipe(cp1);
      pipe(cp2);
      pid1=fork();
      switch(pid1){
        case 0: child1();
        break;
        default:
          pid2=fork();
          switch(pid2){
    	case 0: child2();
    	break;
    	default: parent();
    	break;
          }
          break;
      }
        return 0;
    }
    
    int child1(){
      printf("1 gestartet\n");
      int stop=0;
       close(pc1[1]);
     close(cp1[0]);
      while(!stop){
        printf("1 warte auf startsignal\n");
        read(pc1[0], eab, sizeof(eab)); //warte auf startsignal
      printf("Child 1 Eingabe:\n");
     if(fgets(eab, sizeof(eab), stdin)==NULL)
       stop=1;
     else
    write(cp1[1], eab, sizeof(eab));
    
      }
      close(cp1[1]);
      printf("1 beendet\n");
      return 0;
    }
    
    int child2(){
    printf("2 gestartet\n");
      int stop=0;
       close(pc2[1]);
     close(cp2[0]);
      while(!stop){
        printf("2 warte auf startsignal\n");
        read(pc2[0], eab, sizeof(eab)); //warte auf startsignal
      printf("Child 2 Eingabe:\n");
     if(fgets(eab, sizeof(eab), stdin)==NULL)
       stop=1;
     else
    write(cp2[1], eab, sizeof(eab));
    
      }
      close(cp2[1]);
      printf("2 beendet\n");
      return 0;
    }
    int parent(){
      close(pc1[0]);
      close(cp1[1]);
      close(pc2[0]);
      close(cp2[1]);
      int stop1=0, stop2=0, stop=0;
      while(!stop){
    
        if(!stop1){
          printf("Parent Zweig 1\n");
          write(pc1[1], "sig\0", 5); //schreibe startsignal
          printf("warte auf eingabe\n");
        if(read(cp1[0], eab, sizeof(eab))==0){
          stop1=1;
        printf("EOF erhalten\n");
    
        }
        else
          printf("Ausgabe vom Child 1:%s\n", eab);
      }
      if(!stop2){
      printf("Parent Zweig 2\n");
          write(pc2[1], "sig\0", 5); //schreibe startsignal
          printf("warte auf eingabe\n");
        if(read(cp2[0], eab, sizeof(eab))==0){
          stop2=1;
        printf("EOF erhalten\n");
    
        }
        else
          printf("Ausgabe vom Child 2:%s\n", eab);
        }
    
      if(stop1&&stop2)
        stop=1;
      }
      wait(NULL);
      wait(NULL);
    return 0;
    }
    

    nicht wundern über die vielen printfs, die nehme ich um rauszufinden, wo ich mich grad im Programm befinde.

    wäre schön wenn mir jmd sagen könnte wieso das mit einem child klappt, aber nicht mit 2..



  • um das problem nochmal kurz zu schildern,
    im 1. quelltext wird beim drücken von strg-d im fgets der child-prozess beendet und im parentprozess beim read() die eof-bedingung(0) ausgelöst.
    sobald ich aber noch einen 2. child prozess drinnen habe, wird die eof bedingung nicht mehr ausgelöst, obwohl ich nix anderes mache als noch einen Prozess dazu-.-



  • Des rätsels Lösung:
    Die man muss ALLE nicht benötigten Pipes schließen.
    also auch die pipes, die eigentlich für nen anderen Prozess gedacht sind.
    Nur wieso?!



  • AArgh, ich sollte mich mal anmelden.
    Also ich habs jetzt alles rausgefunden:
    dadurch, dass man 2 Prozesse erzeugt und beide Prozesse die Pipes der anderen mitvererbt bekommen, sind diese weiterhin geöffnet.
    Im Parentprozess wird aufs schließen der pipe nicht reagiert, weil der andere Prozess diese ja noch offen hat.
    Jaa, wenn der Prof sagt man soll alle schließen, dann sollte man das tun xD


Anmelden zum Antworten