Linux fifo blockierend lesen

(Firma: dm2sh) #2605102
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?
#2605584
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?
#2605755
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
(Firma: dm2sh) #2605819
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.
#2606197
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren