FIFO-Problem



  • Ich hab ein ganz einfaches FIFO-Problem. Zwei Programme

    waren erstellt eine FIFO "waren.fifo", ließt Zeilen von der Standardeingabe bis 0 eingegeben wird und schreibt die in die FIFO.

    inventur ließt von der FIFO und schreibt alles in eine Datei (bzw. erstmal reicht der Screen). Wenn niemand mehr auf die FIFO schreibt beendet das Programm, also erst wenn waren.exe geschlossen ist.

    Hab bisher das hier, funktioniert aber nicht wie es soll [siehe unten]:

    // waren:
    
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    
    int main ()
    {
            mkfifo("WAREN.FIFO",0777); // FIFO erstellen
    
            long int warnr = -1;
            unsigned long int warstueck = 0;
    
            FILE* fifo = fopen("WAREN.FIFO","w"); // öffnen,
    
            while(warnr != 0)
            {
                    char line [80];
    
                    printf("INPUT (Form: WarenNr:Stueckzahl):\n");
                    scanf("%s",line); // brav einlesen
    
                    sscanf(line,"%d:%d",&warnr,&warstueck); // schauen ob eh nicht 0 eingegeben wurde für warnr
    
                    if(warnr != 0)
                    {
                            fputs(line,fifo); // in FIFO schreiben
                    }
    
                    fflush(fifo); // damits der gegenüber sofort lesen kann
            }
    
            fclose(fifo); // brav schließen am ende
    
            return(0);
    }
    
    // inventur:
    #include <stdio.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <errno.h>
    
    int main ()
    {
            // fifo nonblocking öffnen
            int fifo = open("WAREN.FIFO",O_RDONLY | O_NONBLOCK);
    
            // hier ausgelesene daten reinschreiben
            FILE* writeto = fopen ("Warenbestand.dat","w");
    
            char zeichen = ' ';
            long int len = 0;
    
            while(true)
            {
                    // lesen von fifo
                    len = read(fifo,&zeichen,1);
    
                    // wenns nicht mehr geht == EOF und die fifo zu ist und nicht nur grad keine daten da sind beenden
                    if(len == 0 && errno != EAGAIN)
                        break;
    
                    if(len > 0) // juhu daten da
                    {
                            // ausgeben
                            fprintf(writeto,"%c",zeichen);
                            printf("%c",zeichen);
                    }
            }
    
            // schließen
            close(fifo);
            fclose(writeto);
    
            return(0);
    }
    

    Probleme:

    inventur beendet nicht wenn waren beendet 😞
    inventur gibt Daten nicht aus 😞

    MfG SideWinder



  • man: read(2) liefert -1 bei einem Fehler, darauf solltest du prüfen.

    btw. immer nur 1 byte zu lesen ist nicht gerade ideal!



  • Das Problem liegt bei inventur, lese ich die FIFO mit cat funktioniert die Sache nämlich schon.

    Derzeit bin ich bei folgendem inventur:

    int fifo = open("WAREN.FIFO",O_RDONLY | O_NONBLOCK);
            FILE* writeto = fopen ("Warenbestand.dat","w");
    
            char zeichen = ' ';
            long int len = 0;
    
            while(true)
            {
                    len = read(fifo,&zeichen,1);
                    //printf("%d Zeichen gelesen.",len); // Funktioniert
    
                    if(len > 0)
                    {
                            printf("Zeichen gelesen."); // Funktioniert nicht mehr
                            fprintf(writeto,"%c",zeichen);
                            printf("%c",zeichen);
                    }
            }
    
            close(fifo);
            fclose(writeto);
    
            return(0);
    

    len ist niemals >0 😞

    MfG SideWinder



  • Jetzt springst du ja garnicht mehr aus der Schleife raus -> es wird auch nie geflusht.
    Machso so:

    if(len == 0)
      break;
    
    if(len > 0)
      write(...);
    


  • ausserdem wäre select() hier auch angebrachter als diese cpu-fressende Schleife (sofern du das überhaupt nicht-blockierend brauchst).



  • Geflushed wird bei mir sowieso nur in waren und nicht in inventur? Oder liegt hier der Fehler?!

    Edit: Mit deiner Änderung gibt er immer erst aus wenn ich waren schließe - y that?

    MfG SideWinder



  • Bei close() in Invenur wird automatisch geflusht.



  • DrGreenthumb schrieb:

    ausserdem wäre select() hier auch angebrachter als diese cpu-fressende Schleife (sofern du das überhaupt nicht-blockierend brauchst).

    Nein aber nmorgen benötige ich auch Non-Blocking-FIFOs und die soll ich ja auch üben für meinen Test 🙂

    MfG SideWinder



  • Edit: Mit deiner Änderung gibt er immer erst aus wenn ich waren schließe - y that?

    printf() ohne einem \n flusht nix. Deshalb auch erst die Ausgabe beim Beenden.



  • DrGreenthumb schrieb:

    Edit: Mit deiner Änderung gibt er immer erst aus wenn ich waren schließe - y that?

    printf() ohne einem \n flusht nix. Deshalb auch erst die Ausgabe beim Beenden.

    omg das wars.

    Ausgabe immer erst am Ende weil ich brav zeichenweise gelesen habe und kein Newline gemacht habe -> das spar ich mir jetzt indem ich einfach zeilenweise lese *g*.

    Und das inventur nicht beendete lag offenbar an && errno != EAGAIN - wann muss ich überhaupt auf EAGAIN prüfen?

    MfG SideWinder



  • man: read(2)

    EAGAIN Non-blocking I/O has been selected using O_NONBLOCK and no data
    was immediately available for reading.



  • Das hab ich auch gelesen - bloß darf ichs ja genau dann nicht einsetzen sondern nur bei ==0 break - also?! 😞

    MfG SideWinder



  • read == 0 -> Dateiende
    read == -1 -> Fehler, errno könnte zB. EAGAIN sein.



  • Okay dann ist alles klar.

    Danke nochmal für eure Hilfe!

    MfG SideWinder


Anmelden zum Antworten