Hallo, ich habe mit mknod name p einen fifo angelegt. Ich kann diesen auch mit fopen öffnen und mit fread bzw. read lesen. Die Leseoperation blockiert auch ein mal. Sobald ich aber einmal etwas in den Fifo reinpipe, wird die blockierung dauerhaft aufgehoben. Eigentlich sollte doch der Inhalt nur einmal auslesbar sein. Der Inhalt wurde also nicht "gelöscht". Wie muss ich das jetzt lösen? Gibt es ein fpops?
Stefan Helmert schrieb: > Hallo, > > ich habe mit mknod name p einen fifo angelegt. Ich kann diesen auch mit > fopen öffnen und mit fread bzw. read lesen. Die Leseoperation blockiert > auch ein mal. > > Sobald ich aber einmal etwas in den Fifo reinpipe, wird die blockierung > dauerhaft aufgehoben. Wie das? Was passiert denn, wenn du nichts mehr reinsteckst? > Eigentlich sollte doch der Inhalt nur einmal auslesbar sein. Ja. Kommt bei dir denn irgendwas mehrfach? > Der Inhalt wurde also nicht "gelöscht". Wurde er nicht?
Rolf Magnus schrieb: > Ja. Kommt bei dir denn irgendwas mehrfach? Ja, der gesamte Inhalt. Es geht immer wieder ganz von vorne los. Mit jeder fread-Operation liest er er den gesamten Inhalt wieder von vorne.
Dann machst du wohl irgendwas falsch, denn das ist nicht das normale Verhalten. Mehr läßt sich jetzt mit den Informationen kaum sagen.
Das jedenfalls läuft wie ich es erwarten würde:
1 | /* Time-stamp: "22.03.12 20:17 lese.c klaus?wachtler.de"
|
2 | *
|
3 | */
|
4 | |
5 | #include <stdlib.h> |
6 | #include <stddef.h> |
7 | #include <stdio.h> |
8 | #include <string.h> |
9 | #include <unistd.h> |
10 | #include <sys/types.h> |
11 | #include <sys/stat.h> |
12 | #include <fcntl.h> |
13 | #include <ctype.h> |
14 | |
15 | int main( int nargs, char **args ) |
16 | {
|
17 | char c; |
18 | int fd = open( "/tmp/a", O_RDONLY ); |
19 | if( fd==-1 ) |
20 | {
|
21 | perror( "war nix mit oeffnen" ); |
22 | exit( 1 ); |
23 | }
|
24 | |
25 | while( 1==read( fd, &c, 1 ) ) |
26 | {
|
27 | printf( "gelesen: %c %3d\n", ( isprint(c) ? c : '?' ), c ); |
28 | }
|
29 | perror( "Fehler beim Lesen" ); |
30 | close( fd ); |
31 | |
32 | return 0; |
33 | }
|
1 | /* Time-stamp: "22.03.12 20:10 schreibe.c klaus?wachtler.de"
|
2 | *
|
3 | */
|
4 | |
5 | #include <stdlib.h> |
6 | #include <stddef.h> |
7 | #include <stdio.h> |
8 | #include <string.h> |
9 | #include <unistd.h> |
10 | #include <sys/types.h> |
11 | #include <sys/stat.h> |
12 | #include <fcntl.h> |
13 | |
14 | int main( int nargs, char **args ) |
15 | {
|
16 | int fd = open( "/tmp/a", O_WRONLY ); |
17 | if( fd==-1 ) |
18 | {
|
19 | perror( "war nix mit oeffnen" ); |
20 | exit( 1 ); |
21 | }
|
22 | |
23 | write( fd, "hallo\n", 6 ); |
24 | close( fd ); |
25 | |
26 | return 0; |
27 | }
|
Ausgabe beim Lesen:
1 | klaus@vdr2:~ > ./lese |
2 | gelesen: h 104 |
3 | gelesen: a 97 |
4 | gelesen: l 108 |
5 | gelesen: l 108 |
6 | gelesen: o 111 |
7 | gelesen: ? 10 |
8 | Fehler beim Lesen: Success |
Also ich mach das so:
1 | #include <stdio.h> |
2 | #include <iostream> |
3 | //#include <fstream> |
4 | |
5 | int main(void) |
6 | { |
7 | FILE* node; |
8 | char text[512]; |
9 | size_t chrs; |
10 | |
11 | |
12 | node = fopen("filter","rb"); |
13 | |
14 | |
15 | while(1){ |
16 | chrs = fread(text,1,512,node); |
17 | printf(text); |
18 | } |
19 | |
20 | |
21 | return 0; |
22 | } |
Da müsste doch das fread immer wieder anhalten, bis wieder was in den Fifo.
nein, das fread scheitert, du merkst es aber nicht und gibst immer wieder das aus, was vom ersten Lesen noch im Puffer steht. Ändere doch mal den Puffer nach dem ersten Lesen, und du wirst sehen, daß beim zweiten Lesen nicht mehr der alte Inhalt wieder gelesen wird. Man könnte auch mal den Rückgabewert vom fread anschauen...
Ja, das zweite Lesen schlägt fehl, soll es aber nicht. Es soll erneut blockieren statt fehlschlagen.
genau genommen schlägt es ja auch nicht fehl, sondern liefert erfolgreich 0 Zeichen :-) Du wirst schon den Rückgabewert deiner Funktion anschauen müssen. Evtl. kann man beim direkten Lesen mit read etwas drehen, aber bei fread fällt mir nichts ein.
Ja, so wie es aussieht, muss nach dem ersten Lesen die Datei/Fifo geschlossen und wieder geöffnet werden...
Warum nimmst du überhaupt die Streamfunktionen, wenn du eh Blöcke lesen willst? Mit den low level-Funktionen hat man z.B. select zum Testen, ob etwas da ist.
So, der Code, den ich schon gepostet habe, funktioniert jetzt. Ich hatte einige geändert und nun wieder diesen ursprünglichen Zustand hergestellt. Ich glaube der Compiler hat sich jetzt an meinem "Programmierstil" gewöhnt.
Klaus Wachtler schrieb: > genau genommen schlägt es ja auch nicht fehl, sondern liefert > erfolgreich 0 Zeichen :-) Es liefert dann 0, wenn man am Ende des Files angekommen ist und dann nochmal versucht zu lesen. Das Fileende kommt bei einem FIFO dann, wenn die Gegenseite ihn schließt. > Du wirst schon den Rückgabewert deiner Funktion anschauen müssen. > > Evtl. kann man beim direkten Lesen mit read etwas drehen, aber bei fread > fällt mir nichts ein. Man könnte feof() verwenden, aber das wäre unsinnig, nur um sich das Auswerten des Rückgabewerts von fread() zu sparen. Stefan Helmert schrieb: > Ja, das zweite Lesen schlägt fehl, soll es aber nicht. Es soll erneut > blockieren statt fehlschlagen. Fehlschlagen tut es nur dann, wenn ein Fehler aufgetreten ist oder die Gegenseite den FIFO geschlossen hat. Praktischerweise kann man sich eine textuelle Beschreibung des Fehlers mit perror() ausgeben lassen.
Stefan Helmert schrieb: > Ich glaube der Compiler hat sich jetzt an meinem > "Programmierstil" gewöhnt. Ich installiere in solchen Fällen immer den DwIm Compiler. DwIm = Do what I mean.
Stefan Helmert schrieb: > Kann es sein, dass nicht das fread blockiert, sondern das fopen? Ja, falls das FIFO noch keine Gegenstelle hat und im blockierenden Modus geöffnet wird, was mit stdio-Funktionen sowieso nicht anders möglich ist. Das alles ist dokumentiert: "man fifo" und "man 7 pipe".
Stefan Helmert schrieb: > chrs = fread(text,1,512,node); > printf(text); Das bitte nie so machen. immer: chrs = fread(text,1,512,node); printf("%s",text); siehe auch hier: http://en.wikipedia.org/wiki/Format_string_attack
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.