From http://pubs.opengroup.org/onlinepubs/009604599/functions/pipe.html:
The pipe() function shall create a pipe and place two file
descriptors, one each into the arguments fildes[0] and fildes[1], that
refer to the open file descriptions for the read and write ends of the
pipe.
There is an example where a parent writes data to its child:
int fildes[2];
const int BSIZE = 100;
char buf[BSIZE];
ssize_t nbytes;
int status;
status = pipe(fildes);
if (status == -1 ) {
/* an error occurred */
...
}
switch (fork()) {
case -1: /* Handle error */
break;
case 0: /* Child - reads from pipe */
close(fildes[1]); /* Write end is unused */
nbytes = read(fildes[0], buf, BSIZE); /* Get data from pipe */
/* At this point, a further read would see end of file ... */
close(fildes[0]); /* Finished with pipe */
exit(EXIT_SUCCESS);
default: /* Parent - writes to pipe */
close(fildes[0]); /* Read end is unused */
write(fildes[1], "Hello world\n", 12); /* Write data on pipe */
close(fildes[1]); /* Child will see EOF */
exit(EXIT_SUCCESS);
}
-
I was wondering how a parent using a pipe to communicate with its child can make sure it will not happen that the child runs read() before the parent runs write, and the child
finish reading before the parent finish writing? -
I was wondering if a pipe created in the parent can be used for
two-way communication between parent and child, or just one way from
the parent to the child not the other way?If the child can send data to parent via the pipe, what will the
program looks like? -
Is a pipe like a real pipe with two ends. fildes[0] and fildes[1]
are used to represent the two ends respectively?If a pipe is two way, what is the meaning of read end and write end
with respect to,i.e.which one read (write), the parent or the child?
Thanks and regards!
O_NONBLOCK,readwill block and wait until data becomes available. So it doesn’t matter; if data isn’t available yet, it will wait for it.fildes[0]is always the reading (output) end, andfildes[1]is the writing (input) end. So you set up one pipe exactly as you have done it (where the parent gets the writing end and the child gets the reading end, so the parent can send to the child), and you set up the other pipe in the opposite manner (you let the parent keep the reading end and give the child the writing end).fildes[0]andfildes[1]do indeed represent the ends of the pipe, but they are not interchangeable. One is used for putting data “into” the pipe, and the other is for getting data “out of” the pipe.If you need more clarification, feel free to ask; I realize this can be confusing for newcomers.
Update to answer questions in comment:
pipe(), and its subprocesses will inherit the file descriptors it receives (unless you close them). That is, they survive through multiplefork()calls. So you can write a program that will give the file descriptors to grandchildren, great-grandchildren, etc. if you want to.pipe()to create the pair (or two pairs if you want bidirectional communication), then forks twice. You can then have one child usefildes[0], and the other child usefildes[1]. The parent should use neither file descriptor. Voilà! Communication between children with a common parent. It’s remarkable how powerful this simple (albeit potentially unintuitive) feature is. This looks something like the example below.fork()as a cloning machine. Before going into the cloning machine, you usepipe()to make a pair of matched walkie-talkies which use a special secret frequency. One can only transmit; the other can only receive. When you use the cloning machine, two copies of you emerge (the original, i.e. parent, and the clone, i.e. child). Each copy is now carrying an identical pair of matched walkie-talkies. If the original destroys his “receive” device and the clone destroys his “transmit” device, then the original can talk to the clone using the walkie-talkies (but not the other way around).But you see, the key idea here is not that
pipe()connects two processes (though that’s its primary use), it’s that it’s something that is duplicated during thefork(). You can re-enter the cloning machine many times and get many walkie-talkies, so what defines “who is talking to whom” (which processes are connected by the pipe) is not a particular aspect of the function of the cloning machine or the walkie-talkies.Rather, it’s determined by who ends up actually using which endpoints, which is entirely in your control. If you wanted, you could have the child close both endpoints (destroy both walkie-talkies), which would leave the parent to talk to himself (this is silly and probably not useful, but it is possible). I realize this was a bit of a tangent, but I’m trying to communicate how the basic idea works so that you understand the realm of things that are possible with pipes.
Example of sibling processes talking with a pipe (unidirectional):