Wie liest man richtig aus einer fifo?

  • Ich habe im Zusammenhang mit meinen AVARDS bzw. dvb-wss-overdrive ein kleines Problemchen, was ich nicht auf die Reihe kriege:
    dvb-wss-overdrive soll dauerhaft laufen und Eingaben, die aus einer fifo kommen, an das vbi-Device der FF weitergeben, also

    Code
    mkfifo /dev/dvb-wss-overdrive
    nohup dvb-wss-overdrive < /dev/dvb-wss-overdrive >&- 2>&- &


    Eingespeist werden sollen in die fifo entweder automatisch generiertes (nohup dvb-aspect > /dev/dvb-wss-overdrive 2>&- &) oder auch statisches (killall dvb-aspect; echo "4:3" > /dev/dvb-wss-overdrive). Das dvb-wss-overdrive durch läuft ist wichtig, um das vbi-Device der FF dauerhaft zu belegen. Im Prinzip funktioniert das auch, aber...
    Die Leseschleife in dvb-wss-overdrive sieht grob so aus:

    Code
    char szInput[100];
      while (scanf("%s", szInput) == 1)
      {
        ...
      }

    Nach dem Starten wartet scanf auch schön auf die Eingaben. Hängt man dann dvb-aspect an die fifo ist auch noch alles in Ordnung, d.h. scanf wartet, bis eine Zeile in die fifo geschrieben wurde, liesst die aus...und das nächsten scanf blockiert wieder, bis wieder was in der fifo steht.
    Wird jetzt aber der erste in die fifo einspeisende Prozess beendet, kehrt scanf ständig mit -1 (eof) zurück (wenn man noch ein while(1) drüber setzen würde)? Erst wenn man wieder einen Prozess an die fifo hängt, wartet scanf wieder braf auf Eingaben...?!

    yaVDR 0.6.2; H61M/U3S3 / G530 / 4GB / GT 520 (passiv) / Cine S2 (Rev. V5.5) + DuoFlex S2 / 120GB SSD (System; SATA>USB) + 3TB SATA 6Gb/s; LCD-TV Toshiba 42VL863G; AVR Yamaha RX-S600...

    Edited once, last by habichthugo ().

  • Ist zwar nicht elegant, aber sowas könnte funktionieren:



    Scanf ist übrigens gefährlich sobald Leerstellen ins Spiel kommen, schau Dir evtl. mal GNU getline an.


    EDIT:
    Was heisst könnte, es funktioniert (sieht aber irgendwie nicht "gewollt" aus das ganze...)

  • So könnte es auch funtionieren, habs allerdings nicht getestet :D


    Ruf scanf() erst in der Schleife auf und werte den Rückgabewert aus.
    z.B.

    VDR1: AMD Duron-1300, 512mb RAM, Nexus-S rev2.1, Airstar 2, Debian Lenny, kernel: 2.6.28-etobi.3, VDR 1.6.0-17 experimental/extensions von Tobi
    VDR2: Athlon XP-M-2600+, 512mb RAM, TT Prem 1.3 DVB-S, Skystar2, Airstar 2, Debian Lenny, kernel: 2.6.28-etobi.3, VDR 1.6.0-17 experimental/extensions von Tobi
    Extern: Activy300, Gen2VDR V2

  • LordJaxom
    ferror sacht nix (is kein Fehler) und clearerr beseitigt (dem zu Folge) das Problem nicht...
    Irgend wie wird für stdin durch das Abhängen des schreibenden Prozesses die Blockierung aufgehoben (O_NBLOCK gesetzt?). Aber warum? getchar etc. verhalten sich übrigens genau so.
    Das mit scanf und den Blanks ist klar (auch dass man den statischen Puffer leicht durch Eingabe eines überlangen Strings zum Überlaufen und damit den Prozess zum Absturz bringen könnte), stört hier aber nicht. Es sollen ja nur ein paar definierte Zeichenketten (4:3, 16:9...) verarbeitet werden.

    yaVDR 0.6.2; H61M/U3S3 / G530 / 4GB / GT 520 (passiv) / Cine S2 (Rev. V5.5) + DuoFlex S2 / 120GB SSD (System; SATA>USB) + 3TB SATA 6Gb/s; LCD-TV Toshiba 42VL863G; AVR Yamaha RX-S600...

  • geeg07
    Ich vermute, Du hast das Problem nicht richtig verstanden bzw. ich habe mich unklar ausgedrückt. scanf soll einfach warten, wenn nix im fifo steht, egal ob an der anderen Seite nun gerade ein Prozess hängt, oder nicht. Hat sich aber der erste schreibende Prozess von der fifo gelöst (z.B. echo "4:3" > /dev/dvb-wss-overdrive), verhält sich stdin als sei es im O_NBLOCK-Modus geöffnet!...?

    yaVDR 0.6.2; H61M/U3S3 / G530 / 4GB / GT 520 (passiv) / Cine S2 (Rev. V5.5) + DuoFlex S2 / 120GB SSD (System; SATA>USB) + 3TB SATA 6Gb/s; LCD-TV Toshiba 42VL863G; AVR Yamaha RX-S600...

    Edited once, last by habichthugo ().

  • Ferror soll auch nichts sagen sondern 1 liefern wenn ein Fehler vorliegt - dass EOF ein Fehler ist habe ich übrigens nirgendwo behauptet. Im Übrigen würde sich das Programm dann ja auch ganz beenden.


    Das mit dem nonblocking Modus ist nicht ganz richtig, da er ja wieder blockiert wenn der nächste Prozess schreibt. Aber bei EOF gibt es (normalerweise) nunmal nichts mehr worauf man warten müsste...


    EDIT:
    Hast Du das Programm wenigstens mal ausprobiert?

  • Quote

    Original von LordJaxom
    Ferror soll auch nichts sagen sondern 1 liefern wenn ein Fehler vorliegt - dass EOF ein Fehler ist habe ich übrigens nirgendwo behauptet. Im Übrigen würde sich das Programm dann ja auch ganz beenden.


    Schon klar.


    Quote

    Original von LordJaxom
    Das mit dem nonblocking Modus ist nicht ganz richtig, da er ja wieder blockiert wenn der nächste Prozess schreibt. Aber bei EOF gibt es (normalerweise) nunmal nichts mehr worauf man warten müsste...


    Na dann müsste scanf ja konsequenter Weise ja schon durchrutschen, bevor der erste Prozess auf die fifo schreibt. Da wird aber hübsch gewartet.


    Quote

    Original von LordJaxom
    EDIT:
    Hast Du das Programm wenigstens mal ausprobiert?


    Jo, genau so hatte ich es gestern abend probiert. Ich hab jetzt grade keinen Zugriff auf meinen VDR.
    Das mit dem sleep wäre ja nur ein Krücke mit der man entweder sinnlos CPU-Zeit verkloppt oder sich eine unnötig hohe Reaktionszeit einhandelt. Aber wenn sich nix besseres findet, werd ichs halt so machen müssen.


    Es muss doch irgend eine Möglichkeit geben, wieder in den Zustand vor dem Andocken eines Prozesses an die fifo zurückzukehen (ohne dvb-wss-overdrive zu beenden und neu zu starten)?

    yaVDR 0.6.2; H61M/U3S3 / G530 / 4GB / GT 520 (passiv) / Cine S2 (Rev. V5.5) + DuoFlex S2 / 120GB SSD (System; SATA>USB) + 3TB SATA 6Gb/s; LCD-TV Toshiba 42VL863G; AVR Yamaha RX-S600...

    Edited once, last by habichthugo ().

  • Das Problem ist IMHO, dass der schreibende Prozess beim beenden die FIFO schliesst und deshalb wird anschliessend in der lesenden Routine eof liefert.
    Ich fürchte fast, der Neustart wird dir nicht erspart bleiben, den könntest du allerdings beim 1. auftreten von eof auslösen, oder?

    VDR1: AMD Duron-1300, 512mb RAM, Nexus-S rev2.1, Airstar 2, Debian Lenny, kernel: 2.6.28-etobi.3, VDR 1.6.0-17 experimental/extensions von Tobi
    VDR2: Athlon XP-M-2600+, 512mb RAM, TT Prem 1.3 DVB-S, Skystar2, Airstar 2, Debian Lenny, kernel: 2.6.28-etobi.3, VDR 1.6.0-17 experimental/extensions von Tobi
    Extern: Activy300, Gen2VDR V2

    Edited once, last by geeg07 ().

  • Wenn das echo "4:3" ... die Probleme macht würde ich überlegen, dieser Art der Signalisierung durch ein eigenes Progrämmchen zu ersetzen (was den FIFO dann _richtig_ öffnet).
    Verhindert zwar nich den Fall, dass doch noch jemand drauf echoed, aber das Grundsystem in sich ist funktionierend.


    arghgra

  • Quote

    Original von geeg07
    Das Problem ist IMHO, dass der schreibende Prozess beim beenden die FIFO schliesst und deshalb wird anschliessend in der lesenden Routine eof liefert.


    Nö, dann würde ein neu gestartetes dvb-wss-overdrive an der selben fifo ja sofort wieder durchrutschen, tuts aber nicht. Ausserdem ist die Schreibseite der fifo ja vor dem ersten Andocken eines Prozesses ja auch geschlossen und dvb-wss-overdrive rutsch nicht durch.


    Quote

    Original von geeg07
    Ich fürchte fast, der Neustart wird dir nicht erspart bleiben, den könntest du allerdings beim 1. auftreten von eof auslösen, oder?


    Neustart würde bedeuten, dass dvb-wss-overdrive das vbi-Device der FF frei gibt was zumindest kurzfristig dazu führt, dass die wieder auf ihr Standardverhalten in der WSS-Signalisdierung zurückfällt, d.h. wenigstens kurzfristiges, unnötiges hin und her geschalte des Bildformats...Nö, ich muss das vbi-Device offen halten, d.h. ich darf den steuernden Prozess nicht beenden.

    yaVDR 0.6.2; H61M/U3S3 / G530 / 4GB / GT 520 (passiv) / Cine S2 (Rev. V5.5) + DuoFlex S2 / 120GB SSD (System; SATA>USB) + 3TB SATA 6Gb/s; LCD-TV Toshiba 42VL863G; AVR Yamaha RX-S600...

  • arghgra:
    Was ist denn bitte "falsch" öffnen? :D


    Nee, im Ernst, wenn jemand etwas in die Datei reinschreibt, öffnet er sie vorher und schliesst sie nachher. Das Problem ist ja auch nicht während des Schreibens sondern zwischen close und neuerlichem open (von aussen).


    Mal sehen, der Unterschied am Anfang ist wohl, dass die Pipe neu (ungeöffnet) ist. Damit wartet ein Lesen solange bis jemand die Datei öffnet. Danach wartet jedes Lesen, bis entweder was geschrieben wurde oder EOF herrscht. Danach ist die Pipe geöffnet und EOF. Löscht man das EOF Flag, kann man nochmal lesen, wenn aber zwischenzeitlich niemand die Pipe zum Schreiben geöffnet hat, kommt wieder EOF (und zwar sofort).


    Man müsste also nach dem ersten EOF die Pipe wieder in den ungeöffnet-Zustand zurücksetzen, nur wie?

  • Quote

    Original von arghgra
    Wenn das echo "4:3" ... die Probleme macht würde ich überlegen, dieser Art der Signalisierung durch ein eigenes Progrämmchen zu ersetzen (was den FIFO dann _richtig_ öffnet).
    Verhindert zwar nich den Fall, dass doch noch jemand drauf echoed, aber das Grundsystem in sich ist funktionierend.


    Die echos braucht man zum Einstellen eines statischen Modus (4:3, 16:9...), wenn die automatische Erkennung des Bildformats (dvb-aspect) mal versagt oder zu viel hin und her schaltet...'Richtiges' Öffnen (via fopen, open etc. auf beiden Seiten) hilft auch nix. Es ergibt sich das selbe Verhalten.

    yaVDR 0.6.2; H61M/U3S3 / G530 / 4GB / GT 520 (passiv) / Cine S2 (Rev. V5.5) + DuoFlex S2 / 120GB SSD (System; SATA>USB) + 3TB SATA 6Gb/s; LCD-TV Toshiba 42VL863G; AVR Yamaha RX-S600...

  • LordJaxom
    Yep! Du hast es (mich) verstanden! :]


    Mal zur allgemeinen Verwirrung:

    Code
    mkfifo a
    echo x > a
    cat a &


    ...würde dazu führen dass cat 'x' ausgibt und sich anschliessend nicht beendet, sondern auf weitere Eingaben via a wartet. Wohingegen...

    Code
    mkfifo a
    cat a &
    echo x > a


    ...dazu führt, dass cat zwar 'x' ausgibt, sich aber anschliessend beendet!??? :rolleyes:

    yaVDR 0.6.2; H61M/U3S3 / G530 / 4GB / GT 520 (passiv) / Cine S2 (Rev. V5.5) + DuoFlex S2 / 120GB SSD (System; SATA>USB) + 3TB SATA 6Gb/s; LCD-TV Toshiba 42VL863G; AVR Yamaha RX-S600...

  • Das kann ich nicht nachvollziehen!


    Wenn ich auf Konsole 1 "echo x > a" starte, wartet echo. Starte ich nun auf Konsole 2 "cat a" gibt er mir x aus. Beide Programme beenden sich danach.


    Wenn ich auf Konsole 1 "cat a" starte, wartet cat. Starte ich nun auf Konsole 2 "echo x > a", so gibt er auf Konsole 1 x aus. Beide Programme beenden sich danach.

  • LordJaxom
    Hm, hatte das von gestern Abend noch so im Gedächnis. Vielleicht wars schon zu spät und ich vertüdel dat heute. Ich guck heute Abend noch ma...Is ja auch Banane!

    yaVDR 0.6.2; H61M/U3S3 / G530 / 4GB / GT 520 (passiv) / Cine S2 (Rev. V5.5) + DuoFlex S2 / 120GB SSD (System; SATA>USB) + 3TB SATA 6Gb/s; LCD-TV Toshiba 42VL863G; AVR Yamaha RX-S600...

  • Quote

    Original von habichthugo
    Mal zur allgemeinen Verwirrung:

    Code
    mkfifo a
    echo x > a
    cat a &


    ...würde dazu führen dass cat 'x' ausgibt und sich anschliessend nicht beendet, sondern auf weitere Eingaben via a wartet. Wohingegen...

    Code
    mkfifo a
    cat a &
    echo x > a


    ...dazu führt, dass cat zwar 'x' ausgibt, sich aber anschliessend beendet!??? :rolleyes:


    und genau dieses Verhalten habe ich gemeint, ich habe das vor meinem letzten Post fast ident getestet.
    Beim ersten Aufruf wird auf den 2. Prozess gewartet, und wenn der endet, schliesst er auch die Pipe, was zu eof im 1. Prozess führt.
    Na vielleicht verstehe ich das Problem doch falsch... :rolleyes:

    VDR1: AMD Duron-1300, 512mb RAM, Nexus-S rev2.1, Airstar 2, Debian Lenny, kernel: 2.6.28-etobi.3, VDR 1.6.0-17 experimental/extensions von Tobi
    VDR2: Athlon XP-M-2600+, 512mb RAM, TT Prem 1.3 DVB-S, Skystar2, Airstar 2, Debian Lenny, kernel: 2.6.28-etobi.3, VDR 1.6.0-17 experimental/extensions von Tobi
    Extern: Activy300, Gen2VDR V2

  • Upps sorry, habe gerade bemerkt, dass doch kleine Unterschiede in unseren Tests bestanden.
    Wenn der Aufruf wie folgt aussieht, wird beendet:

    Code
    mkfifo a
    echo x > a &
    cat < a &

    VDR1: AMD Duron-1300, 512mb RAM, Nexus-S rev2.1, Airstar 2, Debian Lenny, kernel: 2.6.28-etobi.3, VDR 1.6.0-17 experimental/extensions von Tobi
    VDR2: Athlon XP-M-2600+, 512mb RAM, TT Prem 1.3 DVB-S, Skystar2, Airstar 2, Debian Lenny, kernel: 2.6.28-etobi.3, VDR 1.6.0-17 experimental/extensions von Tobi
    Extern: Activy300, Gen2VDR V2

  • Ich habs jetz noch mal in n Varianten durchgespielt: Es ist bei mir jedes mal anders, also nicht reproduzierbar!? Ich hatte jetzt cats, die mehrere echos überlebt haben. Manchmal blockieren die echos, wenn die fifo in der Luft hängt, manchmal auch nicht...?!? :rolleyes:


    Ich hab jetzt einen usleep von 1/10 Sek. in dvb-wss-overdrive reingebaut, der tuts ers ma. Nicht schön, aber...


    Danke ersma @All!


    Wem noch was besseres dazu einfällt, bitte posten!

    yaVDR 0.6.2; H61M/U3S3 / G530 / 4GB / GT 520 (passiv) / Cine S2 (Rev. V5.5) + DuoFlex S2 / 120GB SSD (System; SATA>USB) + 3TB SATA 6Gb/s; LCD-TV Toshiba 42VL863G; AVR Yamaha RX-S600...

  • Das Problem ist, dass Pipes nur für einmalige Benutzung gedacht sind, und danach neu geöffnet werden wollen.
    Wie wär's damit:


    Code
    mkfifo a
    while true ; do cat a ; done | cat &
    echo test > a
    echo test > a


    Anstelle des zweiten cat tritt dann natürlich dein dvb-wss-overdrive.


    Besser wäre es natürlich, dvb-wss-overdrive nicht über stdin zu versorgen, sondern dvb-wss-overdrive selbst die Pipe öffnen zu lassen, um sie bei EOF einfach schließen und erneut öffnen zu können.


    Gruß,


    Udo

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!