Named Pipe
-
# Ziel
Mittels einer "named pipe" sollen Daten zwischen zwei Programmen ausgetauscht werden (Interprocess Communication).# Umgebung
- C++, GNU Compiler
- Linux - Untuntu 8.10
- Code http://web353.s9.benutzer-login.de/files_beyond/code.tar.gz# Funktionstüchtig
Es können über die Konsole (echo "TEXT" > DATEI) übermittelte Daten empfangen werden.# Problem
Die vom "Sendeprogramm" übermittelten Daten werden nur dann empfangen, wenn anschließend mittels der Konsole Daten gesendet werden.
Beispiel:
Sender sendet: "Sender-"
Empfänger: NICHTS
Konsole: "Konsole"
Empfänger: "Sender-Konsole"
Man könnte meinen, die Daten des Senders seien im irgendwo im Zwischenspeicher hängen geblieben. Doch selbst das Beenden des Senders (und damit einem definitiven Flush) bringt keine Verbesserung.Vielen Dank schon mal für eure Mühen
-
Flushst Du denn irgendwo? Dass der Sender beendet wird, heißt ja noch lange nichts.
julius-krebs schrieb:
- Code http://web353.s9.benutzer-login.de/files_beyond/code.tar.gz
Waaah.
- Dass Du von den Leuten hier erwartest, dass sie sich was runterladen, ist schonmal nicht gut, normalerweise stellt man Minmalbeispiele in Code-Tags zur Verfügung, wenn man eine Frage hat.
- Wenn man nicht einfach codepad.org oder Code-Tags verwendet, dann sollte man sich dennoch um ein Minimalbeispiel kümmern und keine Riesen-Ordnerhierarchien hochladen.
- In tarballs verpackt man _ein_ Elternverzeichnis, in dem dann mehrere Unterverzeichnisse liegen. Es ist furchtbar, wenn einem ein "tar xvzf" das Homedir komplett zumüllt.
-
# Flush
Ich habe das direkte Flushen ebenfalls ausprobiert.# Code
- Da das Archiv nur drei Ordner enthält, habe ich die "Zumüllgefahr" nicht so ernst genommen, entschuldige bitte.
- Nun also in Ausschnitten:/* Erstelle Pipe */ umask(0); mknod("/tmp/el_inp_c.pipe", S_IFIFO|0666, 0); /* Read */ fread(data, 1, cnt, file_r); /* Write */ fwrite(data, 1, cnt, file_w); fflush(file_w);
-
Ein _kompilierbares_ Minimalbeispiel wäre toll gewesen.
Aber ohne Ausprobieren: fwrite und Konsorten puffern. Du kannst entweder direkt write und read verwenden, oder Du stellst das Buffering mit man: setvbuf ab.
fflush sollte aber doch auch helfen, oder?
-
# Buffer
- Das Deaktivieren des Buffers hatte ich schon mit setbuf(file, NULL) ausprobiert - ohne Erfolg.
- "Direkt write / read" ist mir neu, wie heißen die entsprechenden Funktionen?
- Mir drängt sich immer mehr die Frage auf, ob es überhaupt am Buffer des Senders liegt.# Code
- Der verlinkte Code ist bereits auf das Wesendliche reduziert (nur eben über mehrere Dateien verteilt) und lässt sich auch direkt compilieren.Vielen Dank für deine Antworten.
-
- "Direkt write / read" ist mir neu, wie heißen die entsprechenden Funktionen?
write und read
-
julius-krebs schrieb:
# Code
- Der verlinkte Code ist bereits auf das Wesendliche reduziert (nur eben über mehrere Dateien verteilt) und lässt sich auch direkt compilieren.Das ist nicht Dein Ernst, oder?
- 81 Dateien
- Kein Toplevel-Makefile
- Keine Angaben, welcher Compiler, welche IDE, welcher Projekttyp
- Keine Angaben, welche Dateien überhaupt am Problem beteiligt sind
Und eh jetzt der Einwand kommt, dass man die fehlenden Angaben als versierter Entwickler schnell herausfinden würde: Das ist nicht unsere Aufgabe. Wir geben Hilfe bei konrekten Problemen (ja, gerne sogar, auch wenn oft gemeckert wird). Aber für die Analyse und Korrektur (oder Fehlerermittlung) eines Gesamtprojekts (auch wenn es klein gehalten ist) würde zumindest ich mich bezahlen lassen.
Zum eigentlichen Thema:
1. Hast Du file_r und file_w einen NULL-Buffer zugewiesen?
2. Zusätzlich zum Buffering kommt auch noch das Blocking - sprich, wenn Du fread sagst, er soll 200 Zeichen lesen, so versucht er das erstmal. Folgendes schaltet das Blocking ab (wodurch fread auch nach weniger Zeichen bereits zurückkehrt - aber eben auch wenn nichts gelesen wurde). Alternativ könntest Du zeichenweise einlesen, bis Du weisst, wieviele Daten vorliegen (entweder indem Du die Länge vorweg schickst oder ein Satzende-Zeichen wie "\n" hinterher).
Oder Du nutzt read/write/select/(e)poll.fcntl(fileno(file_r), F_SETFL, O_NONBLOCK);
-
# Code - allgemein
- Ich dachte mit den Angaben "C++, GNU Compiler, Linux - Untuntu 8.10" sei schon alles gesagt, doch anscheinend täuschte ich mich darin. Leider fällt mir nicht mehr viel dazu ein, die Version kann ich euch noch nennen: 4:4.3.1-1ubuntu2.
- IDE: Netbeans
- Die Dateianzahl hab ich nun um drei nicht verwendete Bibliotheken reduziert, dennoch fällt sie immer noch recht hoch aus. Von der jeweiligen "main.cpp" ausgehend sollte man sich jedoch gut zurechtfinden.# Code - spezifisch
- Der Sender ist im Ordner "el_serial_rc" zu finden, die Makefile befindet sich im Hauptverzeichnis.
- Für den Empfänger verhält es sich ebenso, der Orndername lautet: "el_serial_tr".
- Der Ordner "fo-lib" enthält die von beiden Programmen verwendete Klasse für den Zugriff auf die Pipe.
- http://web353.s9.benutzer-login.de/files_beyond/code2.tar.gz# Buffer
Folgende Punkte wurden geändert, verbessert hat sich dadurch jedoch nichts:
- NULL Buffer für file_r und file_w
- Blocking deaktiviert, wenn auch nicht nötig da die read funktion immer nur auf ein Byte wartet.
- Verwendung von "read" und "write", wobei im grunde überflüsig, da die Buffer bereits deaktivert sind.
-
# Beobachtung
Die empfangenden Daten werden nur dann registriert, wenn eine line feed ('\n') angehängt ist. Und genau das macht die Konsole (mit der es immer einwandfrei geklappt hat) im Gegensatz zu meinem Sender.
Merkwürdig ist, dass dieses Verhalten trotz dem Binary Mode überhaupt auftritt.file_r = fopen("/tmp/el_out_c.pipe", "rb");
# Konsequenz
Da es sich um Binärwerte handelt kann ich meinen Daten nicht einfach ein line feed Steuerzeichen anghängen, da dieses in den Daten selbst vorkommen kann.
Daraus ergibt sich die Frage welche Möglichkeiten es noch gibt, den Empfänger auch ohne line feed Steuerzeichen reagieren zu lassen?