0
votes

I'm trying to understand how pipes work in C. My father process generates the integers from 1 to 10 and writes them in a pipe. My child process has to read the pipe and print the values to screen. The father waits for child termination and exits. Easy, right? Here's my code:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>

#define WRITE 1
#define READ  0
#define N     10

int main(void)
{
    pid_t pid;
    int B0[2];
    int num, status, i;

    pipe(B0);

    pid = fork();
    if (pid > 0){
        /*P0*/
            close(B0[READ]);
            for (i=1; i<=N; i++){
                num = i;
                write(B0[WRITE],&num,sizeof(num));
                printf("P0: written %d\n", num);
            }
            close(B0[WRITE]);

            wait(&status);
            exit(EXIT_SUCCESS);
    }
    else if (pid == 0){
        /*P1*/
        close(B0[WRITE]);
        do{
            if (read(B0[READ],&num,sizeof(num)) != -1)
                printf("P1: read %d from pipe B0\n", num);
            else
                printf("read: %s\n", strerror(errno));
        } while(read(B0[READ],&num,sizeof(num)) != 0);
        exit(EXIT_SUCCESS);
    }
}

I don't understand why as output I receive the following:

P0: written 1
P0: written 2
P0: written 3
P0: written 4
P0: written 5
P0: written 6
P0: written 7
P0: written 8
P0: written 9
P0: written 10
P1: read 1 from pipe B0
P1: read 3 from pipe B0
P1: read 5 from pipe B0
P1: read 7 from pipe B0
P1: read 9 from pipe B0
P1: read 10 from pipe B0

Regardless of the integer sequence I'm writing in the pipe, my read() skips every 2nd value. I've tried to sleep(1) while writing the value to the pipe, but the result is the same. I am missing something, but I don't get what. What's happening?

2

2 Answers

1
votes

You read the 1 and print, then in the while condition, you read the 2 and discard it. Similarly, you discard every even value. The 10 is read in the while condition and returns non-zero so the loop continues, then in the if read returns 0 which is not -1, so you print the 10. Write the loop as while( ( rv = read (... )) != 0 ) { ... }

1
votes

Your do-while loop condition performs read too, but you don't use that value. Instead, you just read again when the loop starts, thus skipping every 2nd value. Either use a different condition, or use the value you've read.