I recreated the example in the man pages for the pipe()
system call and am a little confused as to why the 'Hello world'
message is printed when the parent process seems to complete before the child process:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
const int BSIZE = 100;
int fildes[2];
char buff[BSIZE];
pipe(fildes);
pid_t rc = fork();
if (rc == 0) {
printf("in child\n");
close(fildes[0]);
write(fildes[1], "Hello world\n", 13);
close(fildes[1]);
} else {
printf("in parent\n");
close(fildes[1]);
read(fildes[0], buff, BSIZE);
close(fildes[0]);
printf("%s", buff);
}
return 0;
}
The output from this looks like:
in parent
in child
Hello world
From the output it looks like the parent process is finishing before the child process runs. If so, how does Hello world
print? If read
is called before the child process finishes writing i would expect buff
to be empty (or at least incomplete) when read
is called.
I to remove the close()
calls to see if read()
was waiting on the other end to close or if the pipe()
method waited, but I got the same results.
Is this just a timing thing? It just happens to finish this way and I should be adding a `wait()` call in the parent process?
I didn't the answer in the man page for pipe()
, and couldn't phrase it properly for google, so I thought I would try and ask here.
Thanks
The order of two output lines in parent
and in child
is not defined.
In the parent process read(fildes[0], buff, BSIZE)
is a blocking read of at least 1 byte from the pipe. You can convince yourself of that, for example, by adding a sleep(3)
before the child write(fildes[1], "Hello world\n", 13);
. The write will be atomic as it's less than PIPE_BUF
bytes. This effectively synchronizes the child and parent processes so the parent printf("%s", buff);
happens last. The pipe will buffer the data if the client happens to exit before the parent.
Here's a slightly revised version of your program which shows you that the parent exists after the client:
#include <stdio.h>
#include <unistd.h>
#define BSIZE 100
int main() {
int fildes[2];
pipe(fildes);
if (fork()) {
char buff[BSIZE];
printf("in parent\n");
close(fildes[1]);
read(fildes[0], buff, BSIZE); // blocking
close(fildes[0]);
printf("%s", buff);
printf("out parent\n");
} else {
printf("in child\n");
close(fildes[0]);
// sleep(3);
write(fildes[1], "Hello world\n", 13);
close(fildes[1]);
printf("out child\n");
}
}
which example output:
in parent
in child
out child
Hello world
out parent
This suggest the parent exists after the client.