0

I have composed the 2 following programs, in one I continuously write a string to a buffer and pass it through the FIFO to the other one, which reads what I've passed.

/*write*/
int main()
{
    int i=0, fd1;
    char buffer[16];

    mkfifo("fifo1", 0666);

    fd1 = open("fifo1", O_WRONLY);

    for(;;)
    {
        sprintf(buffer, "string%d", i);
        write(fd1, buffer, 16);
        i++;
    }
}

/*read*/
int main()
{
    int i=0, fd1;
    char buffer[16];

    fd1 = open("fifo1", O_RDONLY);

    for(;;)
    {
        sleep(1);
        read(fd1, buffer, 16);
        printf("%s\n", buffer);
    }
}

So,I wanted to analyze the behaviour between these two programs. I opened 2 terminals. In the first one I ran the write program first and in the second one I ran the read program. After seeing the read program printing some of the strings, I stopped the execution of the write program(through keyboard), to examine what happens. The read program, even though I had stopped the write program, kept printing strings.

Can someone explain to me the behaviour of these two programs? What exactly happens?

(I didn't bother writing function checking)

tiempo
  • 121
  • 2
  • 14
  • I assume the read program eventually stopped printing, right? I'm guessing you're just seeing buffering artifacts: It's a lot faster to IPC between processes than to print to the terminal, so it would take the terminal a while to catch up. – ShadowRanger Apr 25 '17 at 19:36
  • @ShadowRanger No, it keeps printing strings and in the correct order. – tiempo Apr 25 '17 at 19:49
  • 1
    Pipes usually buffer a few KB of data. Given your 1s sleep time between printing results, your read program will probably print strings with increasing numeric values for a few tens of minutes after you stop the write program. And then it will print the last string it received over and over forever. (That is assuming you get no partial `read()` results - `read()` reads *up to* the number of bytes requested - it can always return less than that.) – Andrew Henle Apr 25 '17 at 20:05
  • @Andrew Henle Any idea how they buffer the data, since their size is 0? – tiempo Apr 25 '17 at 20:20
  • @Q_M *Any idea how they buffer the data, since their size is 0?* [Here's the code that does the buffering -for Linux, anyway.](http://lxr.free-electrons.com/source/fs/pipe.c#L356) The data is copied into kernel memory - where it's read from by the reading process. A pipe reports a zero size because it has no real "size" - you can't seek to the Nth byte to read that byte - over and over again, if you want. A pipe is for a *stream* of bytes, written and read in order. Once you read a byte, it's gone from the stream. – Andrew Henle Apr 25 '17 at 21:55
  • @Andrew Henle Thanks for your time and answer. If you want copy and paste your comments as an answer so I can accept it. – tiempo Apr 25 '17 at 23:02
  • You should be error checking your `read()` call so you know when you reach EOF. As it stands, it will continue 'reading' indefinitely, eventually just printing the same thing over and over again. It'll take a while because of the `sleep(1)` in there (it could easily be more than an hour before you see that behaviour); you might want to investigate `usleep()` or `nanosleep()` — `usleep()` is easier to use but deprecated. – Jonathan Leffler Apr 25 '17 at 23:39

1 Answers1

2

When you launch both the program the "read" and "write" end of a FIFO is opened, as you do the message transaction by writing and reading it works fine, read gets blocked until some program writes to it.

as soon as you terminate the writing program you have closed one end of FIFO and the connection broke. so Now "read" will every time read EOF and return 0, you will end up in non-blocking of read case. In your case you are not clearing buffer so the Old value will be printed.

you can open and close connections for every Message so even if you close the "write" process abruptly, the next open call of the "read" process will get blocked until some process opens "write" end.

Note: I have ignored API error return types here.

/*write*/
int main()
{
    int i=0, fd1;
    char buffer[16];

    mkfifo("fifo1", 0666);


    for(;;)
    {
        fd1 = open("fifo1", O_WRONLY);
        sprintf(buffer, "string%d", i);
        write(fd1, buffer, 16);
        i++;
        close(fd1);
    }
}

/*read*/
int main()
{
    int i=0, fd1;
    char buffer[16];

    fd1 = open("fifo1", O_RDONLY);

    for(;;)
    {
        fd1 = open("fifo1", O_RDONLY);
        sleep(1);
        read(fd1, buffer, 16);
        printf("%s\n", buffer);
        close(fd1);
    }
}