Search code examples
clinuxmkfifo

Not all messages written to FIFO received on read


I've got a strange problem when working with fifo files in C under linux.

Let's begin with the code:

#include<stdio.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>

int main(int args, char *argv[])
{
mkfifo("fif",0666);
int x = fork();

if(x!=0)
{
     if(strcmp(argv[1],"read")==0)
     {
     int rea=open("fif",O_RDONLY,0666);
     wait(NULL);
     char buf[50];
     read(rea,buf,50);
     printf("\n %s \n",buf);
     close(rea);
     }
}

else
{
     if(strcmp(argv[1],"write")==0)
     {
     int wri=open("fif",O_WRONLY,0666);
     write(wri,argv[2],strlen(argv[2])+1);
     close(wri);
     }
}



return 0;
}

Now some details on what I want the code to do.

After running program like this:

./prog write hello
./prog write how
./prog write are_you
./prog read

I want to have in terminal:

hello
how
are_you

But instead of this, I'm only getting this:

are_you

The problem is: I want to write to FIFO several messages, and then by reading the FIFO, it is intended to receive whole text which is stored in it. But unfortunately only the last message is stored/writed on the standard output (terminal in this case), like the only command was executed is:

./prog write are_you

I tried to remove this line:

mkfifo("fif",0666);

Because I thought, if the FIFO file already exists, this line could create and overwrite the existing FIFO file. But this didn't change anything.

So what I have to do to make this working as intended?


Solution

  • First, notice that you are writing the terminating \0 character into the FIFO:

     write(wri,argv[2],strlen(argv[2])+1);
    

    When you read the contents of the fifo you also read the \0 characters, and pass the data to printf. The thing is, printf stops reading the string when it finds the first \0 so you'll only see the first message from the fifo.

    You can see this clearly if you run the read program under strace:

    read(3, "are_you\0hello\0how\0", 50)    = 18
    ...(snip)...
    write(1, " are_you \n", 10)             = 10