0
votes

I have two programs to write and read a FIFO. One is read(O_RDONLY) a FIFO. Another is write data into this FIFO. This is code:

Read: The executable file is named read.

#include<errno.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<string.h>

int main(int argc, char *argv[])
{
    int fd, nread;
    const char *pipe_file = "/tmp/test_fifo";

    char buf[0x100] ;

    fd = open(pipe_file, O_RDONLY);

    while(1) {
        printf("\n"); /*  */
        memset(buf, 0, 100);
        nread = read(fd, buf, 0x100);
        printf("data is %s", buf);
        sleep(1);
    }

    return 0;
}

Write: The executable file is named write.

#include<errno.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<string.h>

int main(int argc, char *argv[])
{
    int fd;
    int num = 1234;
    char *s = "changzhi";
    const char *pipe_file = "/tmp/test_fifo";


    fd = open(pipe_file, O_WRONLY);
    write(fd, s, strlen(s));

    return 0;
}

The FIFO named /tmp/test_fifo is already exists. When I run read to read FIFO and run write to write the FIFO, everything goes ok. But, the read can not read data when there is no printf("\n"); in read code. I don not know why. Could someone help me ? Thanks a lot!

2
Note that there are system-provided commands called read and write. Are you sure you aren't accidentally using one of those? (You will be OK if you use ./read and ./write, for example.) In your code, you don't check that your open succeeds; you don't report that your open succeeded; you don't check that your read or write operations succeed; you don't report when the write has succeeded. You need to run the programs in parallel: ./read & ./write or ./write & ./read. - Jonathan Leffler

2 Answers

2
votes

Your second printf() is buffered until the \n is written. The read is not blocked :-)

Rewrite your loop:

while(1) {
    memset(buf, 0, 100);
    nread = read(fd, buf, 0x100);
    printf("data is %s\n", buf);
    sleep(1);
}
0
votes

With cleanly compiling code under stringent compilation options:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>     -Wold-style-definition -Werror write.c -o write
$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>     -Wold-style-definition -Werror read.c -o read
$

the code basically works for me. I've added error checking. The slightly odd argv[argc-argc] prints argv[0] but avoids a warning (error because of -Werror) about argc being unused.

read.c

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int fd, nread;
    const char *pipe_file = "/tmp/test_fifo";

    char buf[0x100];

    if ((fd = open(pipe_file, O_RDONLY)) < 0)
    {
        fprintf(stderr, "%s: Failed to open FIFO %s\n", argv[argc-argc], pipe_file);
        return 1;
    }
    printf("%s: open successful\n", argv[0]);

    while(1) {
        printf("\n"); /*  */
        memset(buf, 0, 100);
        nread = read(fd, buf, 0x100-1);
        if (nread <= 0)
            break;
        printf("data is %s\n", buf);
        sleep(1);
    }

    return 0;
}

write.c

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    int fd;
    char *s = "changzhi";
    const char *pipe_file = "/tmp/test_fifo";

    if ((fd = open(pipe_file, O_WRONLY)) < 0)
    {
        fprintf(stderr, "%s: failed to open FIFO %s\n", argv[argc-argc], pipe_file);
        return 1;
    }
    printf("%s: open successful\n", argv[0]);
    if (write(fd, s, strlen(s)) <= 0)
    {
        fprintf(stderr, "%s: failed to open FIFO %s\n", argv[argc-argc], pipe_file);
        return 1;
    }
    printf("%s: write successful\n", argv[0]);

    return 0;
}

Sample output

$ ./read & ./write
[1] 85542
./write: open successful
./write: write successful
./read: open successful

data is changzhi
$ 

[1]+  Done                    ./read
$ ./write & ./read
[1] 85544
./write: open successful
./read: open successful

./write: write successful
data is changzhi

[1]+  Done                    ./write
$

The programs report an error sensibly if the FIFO does not exist.