Non-blocking FIFO

  • Hi zusammen,
    Ich bin gerade dabei ein Programm zu schreiben, hier wird die kommunikation zwischen zwei Programmen am Raspberry benötigt.
    Dies habe ich mit einer FIFO Queque gelöst nun ist aber mein Problem dass ich parallel zum FIFO lesen noch etwas machen will und in die FIFO auch nur zu bestimmten Events rein schreibe.
    Nun meine Frage gibt es irgendeine Abfrage sowas wie

    Code
    fifo.available()

    , dass es mir ermöglicht einfach solange da nichtrs verfügabr ist auch nicht die FIFO dauernd abzufragen :s

    Hoffe meine Fragestellung ist klar, wenn gewünscht kann ich auch noch meinen Code posten.

    Vielen Dank schonmal für die Hilfe
    Schönes Wochenende
    Benedikt

  • Hallo Benedikt,

    schaue Dir bitte mein Tutorial zu IPC in Icon an. Die Technik in Python ist identisch.

    Ansonsten bleibt Dir, die Dateigrösse der FIFO-Datei auszulesen, um auf einen Inhalt zu prüfen.

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (13. Mai 2017 um 14:07)

  • Also wenn ich das richtig verstanden habe muss ich in meiner FIFO einfach drauf abfragen ob NULL bekomme wenn ich dies tue, dann mach ich weiter im Programm oder wie?
    Also sollte die Zeile if(fifo.read() == NULL) oder so ähnlich bin mir bei der syntax nicht so sicher den Fehler kompensieren?

  • Hallo Benedikt,

    der entscheidende Punkt ist der, dass der Schreibvorgang erst abgeschlossen werden kann, nachdem der Lesevorgang abgeschlossen wurde. Das ist der große Unterschied zwischen FIFO- gegenüber herkömmlichen Dateien. Das vereinfacht die Kommunikation - ist aber für Programmierer ohne FIFO-Erfahrung vom Verständnis her ungewohnt.

    Wenn der "Empfänger" nichts auslesen kann, dann hat der "Sender" auch nichts gesendet.

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (13. Mai 2017 um 15:38)

  • Hallo Andreas,

    Um nochmal alle unklarheiten zu beseitigen:
    Programmablauf(grob):

    Handy sendet Nachricht an Raspberry
    Skript wird aufgerufen, welches in die Pipeline schreibt und wieder geschlossen

    Main:
    Abfrage ob ich von meinem 2.4GHz Modul Daten empfangen habe
    oder eben etwas in der FIFO drinnen steht und je nachdem etwas ausführt.

    Du sagst jetzt swoiet ich das verstanden habe, dass "parallel" zum FIFO auslesen nichts machen kann, da er immer drauf wartet dass was geschrieben wird?
    oder: dass ich auf null abfragen muss und wenn null, also nichts drinnen steht da irgendwie rauskomme?

    Wenn oder der fall ist wäre mir noich ein timeout eingefallen aber dann müsste ich ja an dem FIFO "Bausatz" rumschreiben.

    Bin leider echt neu mit der FIFO und verstehe bis jetzt eben nur Grundlagen udn was es macht, aber die Möglichkeiten eben noch nicht.

  • Hallo Benedikt,

    schau doch mal hier vorbei.

    Demnach funktioniert IPC mit FIFO folgendermaßen:

    • Sender schreibt in FIFO-Datei
    • Empfänger versucht gelegentlich, den Inhalt auszulesen. Entweder ist / war was drin - dann hat es jetzt der Empfänger. Die Datei ist dann leer. Oder es war nichts drin - der Sender hat nichts Neues geschickt. Die Datei bleibt leer.
    • Der Sender kann den Schreibvorgang erst abschließen, nachdem der Empfänger gelesen hat. Die Datei erst dann geschlossen.
    • Den Status kannst Du an der Dateigröße und dem Zustand offen/geschlossen und ggf. ab der Position des Schreib-/Lesezeigers erkennen.



    Du sagst jetzt swoiet ich das verstanden habe, dass "parallel" zum FIFO auslesen nichts machen kann, da er immer drauf wartet dass was geschrieben wird?
    oder: dass ich auf null abfragen muss und wenn null, also nichts drinnen steht da irgendwie rauskomme?


    Der Empfänger kann alles machen. Er hat ja selbst die Kontrolle, wann der Sender die Datei schließt und überhaupt wieder was schreiben darf (wenn er was zu schreiben hat). Der Empfänger kann sich zwischen zwei Lesevorgängen alle Zeit der Welt lassen und alles machen, wonach Dir der Sinn steht.
    Der Empfänger kann es sich erlauben, nach Belieben nach neuen Daten zu schauen.



    Wenn oder der fall ist wäre mir noich ein timeout eingefallen aber dann müsste ich ja an dem FIFO "Bausatz" rumschreiben.

    Bin leider echt neu mit der FIFO und verstehe bis jetzt eben nur Grundlagen udn was es macht, aber die Möglichkeiten eben noch nicht.

    Wie gesagt, schau Dir mein Tutorial dazu an. Da sind zwei Beispiele. Das eine überträgt Kommandos, das andere verpflanzt Variablen und ihre Inhalte von einem Programm in das andere. Das lässt sich 1:1 in Python übertragen.


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    2 Mal editiert, zuletzt von Andreas (17. Oktober 2017 um 23:02)


  • Um nochmal alle unklarheiten zu beseitigen:
    Programmablauf(grob):

    Handy sendet Nachricht an Raspberry
    Skript wird aufgerufen, welches in die Pipeline schreibt und wieder geschlossen

    Main:
    Abfrage ob ich von meinem 2.4GHz Modul Daten empfangen habe
    oder eben etwas in der FIFO drinnen steht und je nachdem etwas ausführt.

    Du hast also 2 unterschiedliche Scripts die unabhängig voneinander ausgeführt werden?
    Das eine läuft permanent das andere nur sporadisch? Und nun möchtest du dass das "sporadisch"-laufende quasi Mitteilungen/Aufgaben für das "Main"-Script hinterlassen kann?
    Was macht das "Main"-Script denn sonst noch?

    Evtl. würde sich auch Socket dafür anbieten wenn das "Main"-Script sowieso die ganze Zeit läuft. Dann verbindet sich das "sporadisch"-Script einfach zum "Main"-Script und setzt nen Befehl oder was auch immer ab.

    Alternativ besteht auch die Möglichkeit ein Queue-Server zu verwenden. Sowas nutz ich ebenfalls als IPC recht erfolgreich: beanstalkd (python module: pystalkd oder beanstalkc)
    Der Queue-Server läuft unabhängig und permanent. Scripts können sich nach Bedarf einklinken und bestimmte Queue's abrufen, löschen, erstellen was auch immer - ist sogar Netzwerkfähig.

  • Du hast also 2 unterschiedliche Scripts die unabhängig voneinander ausgeführt werden?
    Das eine läuft permanent das andere nur sporadisch? Und nun möchtest du dass das "sporadisch"-laufende quasi Mitteilungen/Aufgaben für das "Main"-Script hinterlassen kann?
    Was macht das "Main"-Script denn sonst noch?

    Richtig das eine schreibt der Main was sie zu tuen hat bzw weiter zu schicken hat und wird dannach wieder geschlossen.
    Das Mainskript soll "parallel" dazu noch auf Befehle von einem Arduino über ein 2.4GHz Modul warten -> z.B Temperatur, oder ähnliche Signale.
    Und eben je nachdem was das "sporadische" Skript für Aufgaben verteilt diese Aufgaben erledigen (über das 2.4Ghz Modul unterschiedliche Befehle an das Arduino senden)


    Wenn die FIFO so wie Andreas das erklaärt hat funktioniert verstehe ich nicht wieso mein Porgramm dann nicht funktioniert bzw. wieso das Programm dann funktioniert, wenn ich den
    open FIFO und read FIFO-Befehl auskommentiere. Daher bin ich nämlich erst auf das Problem gestoßen.

    Edit: Habe mir jetzt mal den Socket angeschaut funktioniert das dann im Endeffekt so:
    Main:

    Anderes skript:
    selbes wie oben bloß mit

    Code
    c.connect()
    c.send(line)

    oder hab ich da was falsch vertsanden?


    Werde mir das alles mal anschauen vielen Dank erstmal für die Antworten!

    Einmal editiert, zuletzt von BenediktSch (14. Mai 2017 um 20:50)

  • Das wäre sozusagen die Basis, ja. Es fehlt aber noch das schließen der Verbindung und wenn deine Main parallel auch noch was anderes machen soll brauchst du einen weiteren Thread.

    Wenn du detaillierte Hilfe brauchst dann zeig bitte dein Main Script.

  • Also die main is echt nicht komplexes ich fassse es grob zusammen dass die Kernteile erhalten sind:

    Wenn du den ganzen code brauchst kann ich ihn natürlich zur Verfügung stellen aber ist wie gsagt viel if else und initialsierung mehr ist da eigentlich fast nicht
    Da ich aber das auch gern "selber machen" würde wäre es auch nett wenn du mir evtl nur die bnötigten utensilien zur verfügung stellst. also was ich jetzt raus gelesen habe:
    threading und sockets richtig? threading hab ich leidee so garnicht verstanden also was brigen mir 2 threads? (das ganze muss ganz und garnucht parallel laufen das läuft bja normal so schnell durch dass es quasi parallel ist.

    Einmal editiert, zuletzt von BenediktSch (15. Mai 2017 um 00:36)

  • Eine Zusammenfassung ist nahezu nutzlos.

    Das Script selbst ist ein Thread und wenn dort sowas wie eine Schleife läuft wird alles andere in diesem Thread blockiert - die volle Aufmerksamkeit erhält nur die Schleife. In einem Thread kann auch nur eines gleichzeitig bearbeitet/abgearbeitet werden. Um parallel mehrere Sachen behandeln zu können bedarf es mehrerer Threads oder Prozesse.

    Wenn du also gleichzeitig sowohl Empfangenes vom Arduino also auch Socket verarbeiten willst, brauchst du ... ? Einen weiteren Thread oder Prozess ;)

    Du könntest auch das empfangen vom Arduino in ein weiteres Script aufteilen und deine Main.py verarbeitet dann beides einfach nur... Möglichkeiten gibt es wie immer viele..

    Wenn dir Zeitgleiche parallele Behandlung nicht so wichtig ist könntest du das aber auch einfach Nacheinander behandeln - dann empfehle ich dir aber Funktionen oder Klassen für deine einzelnen wichtigen Dinge zu erstellen.

  • Du könntest auch das empfangen vom Arduino in ein weiteres Script aufteilen und deine Main.py verarbeitet dann beides einfach nur... Möglichkeiten gibt es wie immer viele..

    Also der Socket läuft jetzt einwandfrei trotzdem habe ich noch das Gefühl dass das auslesen blockiert? Aber gestern hat das 2.4GHz Modul nicht funktioniert desdwegen kann ich es nicht mit Sicherheit sagen. Werde im Verlaufe des Tages mal schaun dass das 2.4GHz Modul wieder läuft (wieso es nicht läuft kann ich mir nicht erklären, da ich am code nichts geändert habe...)
    Und dann entweder das wie du gesagt hast mit einem zweiten Skript oder mit Threads probieren und dann über den Socket einfach mit der Main.py kommunizieren.
    Hoffe das haut hin!

    Sollte was nicht klappen rühre ich mich noicheinmalund du kriegst den ganzen "schölnen" Code zugesicht :D ! Aber danke schonmal für die Hilfestellung.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!