Forum: PC-Programmierung Linux fifo blockierend lesen


von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

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?

von Rolf M. (rmagnus)


Lesenswert?

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?

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

Dann machst du wohl irgendwas falsch, denn das ist nicht das normale 
Verhalten. Mehr läßt sich jetzt mit den Informationen kaum sagen.

von Klaus W. (mfgkw)


Lesenswert?

Wahrscheinlich scheitert das Lesen, aber er ignoriert den Fehler?

von Klaus W. (mfgkw)


Lesenswert?

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

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

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.

von Klaus W. (mfgkw)


Lesenswert?

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...

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

Ja, das zweite Lesen schlägt fehl, soll es aber nicht. Es soll erneut 
blockieren statt fehlschlagen.

von Klaus W. (mfgkw)


Lesenswert?

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.

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

Ja, so wie es aussieht, muss nach dem ersten Lesen die Datei/Fifo 
geschlossen und wieder geöffnet werden...

von Klaus W. (mfgkw)


Lesenswert?

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.

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

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.

von Klaus W. (mfgkw)


Lesenswert?

ja, bestimmt

von Rolf M. (rmagnus)


Lesenswert?

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.

von DwIm (Gast)


Lesenswert?

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.

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

Kann es sein, dass nicht das fread blockiert, sondern das fopen?

von Andreas B. (andreas_b77)


Lesenswert?

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".

von tamptus (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.