1

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?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441

1 Answers1

2

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
Joni
  • 108,737
  • 14
  • 143
  • 193
  • What you see in the terminal is the *first* string *read* from the fifo. I'm not sure what determines the order of strings in the fifo but I would guess it depends on process scheduling because the writer processes are waiting for the fifo to open. – Joni Nov 11 '14 at 13:58
  • In fact, never write a `\0` in a pipe, you will only get troubles. The `\0` are only needed in string variables. – Edouard Thiel Nov 11 '14 at 14:04
  • `char buf; while(read(rea,&buf,1)) if(buf=='\0') printf("\n"); else printf("%c",buf); ` This solved a problem. It prints the whole FIFO, including `\0` properly. However the messages are written in reverse order. – BigMacintosh Nov 11 '14 at 14:36