poorprogramerqq
poorprogramerqq

Reputation: 47

How can I use FIFO to wait someone write in and read?

As title, I use C to do this job between two programs in Linux system. But, I encounter some problem. Assuming that I have a server write data to FIFO in ten rounds, and the client will read each round data and write another FIFO to feed back to server. The client will block in each round until that the server writer data in. However, my client program can't do this.

I use fopen to open the FIFO and fgets to read data. It seems not to block to wait data write in.

client code:

FILE *fp_R,*fp_W;
char temp[100];
fp_R = fopen(FIFO_R,"rb");
fp_W = fopen(FIFO_W,"wb");
for ( i = 0 ; i < 10 ; i ++ ) {
   fgets(temp, 100, fp_R);
   Handle Data;
   fprintf(fp_W,DATA);
}

I want to fgets to wait for server writing data in, so that I can handle each round

Thanks for anyone help

Upvotes: 3

Views: 2693

Answers (3)

Peter Cordes
Peter Cordes

Reputation: 363999

read(2) on a fifo will block until there's data available, or the writing side close(2)es its open FD. (In which case you will get EOF).


Run your program under strace, to see the system calls it makes.

e.g.

Reading side

peter@tesla:/tmp$ mkfifo mypipe
peter@tesla:/tmp$ strace cat mypipe
execve("/bin/cat", ["cat", "mypipe"], [/* 69 vars */]) = 0
...
open("mypipe", O_RDONLY   # blocks until a writer opens the fifo
...    # after starting the writing side:
                = 3
fstat(3, {st_mode=S_IFIFO|0664, st_size=0, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = -1 ESPIPE (Illegal seek)
mmap(NULL, 139264, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f70d245c000    # cat allocates a buffer.  This might be from C stdio, or more likely custom buffering in GNU cat
read(3, "lkjsalkfj\n", 131072)          = 10
write(1, "lkjsalkfj\n", 10lkjsalkfj
)             = 10
read(3,   # blocked on a read system call

Writing side:

note that my shell opened the pipe before running cat. I could have done
strace tee /tmp/mypipe > /dev/null

$ strace cat > /tmp/mypipe
... 
read(0, lkjsalkfj
"lkjsalkfj\n", 131072)          = 10
write(1, "lkjsalkfj\n", 10)             = 10

So the suggestions to add a sleep(3) are nonsense. Your code looks like it should work. You're probably doing something else wrong, and you should use strace to find it, since that's often easier than adding error-checking to your system calls in toy programs. Most of the code in real systems programming is checking error conditions from system calls, and handling them.

I wouldn't be surprised if your reads aren't blocking because they're returning right away with an error.

Upvotes: 1

Stubborn
Stubborn

Reputation: 780

Add 1 line and try as below:

int fp_R,fp_W;
char temp[100];
fp_R = fopen(FIFO_R,"rb");
fp_W = fopen(FIFO_W,"wb");
for ( i = 0 ; i < 10 ; i ++ ) {
   sleep(1); or usleep(10);//try it fgets will wait for some time bcz of this
   fgets(temp, 100, fp_R);
   Handle Data;
   fprintf(fp_W,DATA);
}

Upvotes: 0

Liu Hao
Liu Hao

Reputation: 512

as TonyB said, the fopen() function will return a file pointer FILE*

FILE *fp_R, *fp_W;
char temp[100];
fp_R = fopen(FIFO_R,"rb");
fp_W = fopen(FIFO_W,"wb");
for ( i = 0 ; i < 10 ; i ++ ) {
   char* ret = fgets(temp, 100, fp_R);
   while(ret == null)
   {
    Sleep(1);
   }
   Handle Data;
   fprintf(fp_W,DATA);
}

Upvotes: 1

Related Questions