16.10.3. Discussion
Pipes are simply two connected filehandles, where data written to one
filehandle can be read by the other. The pipe
function creates two filehandles linked in this way, one writable and
one readable. Even though you can't take two already existing
filehandles and link them, pipe can be used for
communication between processes. One process creates a pair of
filehandles with the pipe functions, then forks
off a child, resulting in two distinct processes both running in the
same program, each with a copy of the connected filehandles. As with
open, if pipe is passed
undefined scalars instead of filehandles, it creates filehandles in
those scalars.
It doesn't matter which process is the reader and which is the
writer, so long as one of them takes one role and its peer process
takes the other. You can only have one-way communication. (But read
on.)
Example 16-4. pipe2
#!/usr/bin/perl -w
# pipe2 - use pipe and fork so child can send to parent
use IO::Handle;
my ($reader, $writer);
pipe($reader, $writer);
$writer->autoflush(1);
if ($pid = fork) {
close $writer;
chomp($line = <$reader>);
print "Parent Pid $$ just read this: `$line'\n";
close $reader;
waitpid($pid,0);
} else {
die "cannot fork: $!" unless defined $pid;
close $reader;
print $writer "Child Pid $$ is sending this\n";
close $writer; # this will happen anyway
exit;
}
In most code, both halves would go into loops, with the reader
continuing to read until end-of-file. This happens when the writer
closes or exits.
Because piped filehandles are not bidirectional, each process uses
just one of the pair and closes the filehandle it doesn't use. The
reason is subtle; picture the situation where the reader does not
close the writable filehandle. If the writer then exits while the
reader is trying to read something, the reader will hang forever.
This is because the system won't tell the reader that there's no more
data to be read until all copies of the writable filehandle are
closed.
The preceding examples were unidirectional. What if you want both
processes talking to each other? Just make two calls to
pipe before forking. You must be careful about who
tells whom what and when, though, or you're apt to deadlock. (See
Example 16-7.)
Example 16-8. pipe6
#!/usr/bin/perl -w
# pipe6 - bidirectional communication using socketpair
# "the best ones always go both ways"
use Socket;
use IO::Handle;
# We say AF_UNIX because although *_LOCAL is the
# POSIX 1003.1g form of the constant, many machines
# still don't have it.
socketpair($child, $parent, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
or die "socketpair: $!";
$child->autoflush(1);
$parent->autoflush(1);
if ($pid = fork) {
close $parent;
print $child "Parent Pid $$ is sending this\n";
chomp($line = <$child>);
print "Parent Pid $$ just read this: `$line'\n";
close $child;
waitpid($pid,0);
} else {
die "cannot fork: $!" unless defined $pid;
close $child;
chomp($line = <$parent>);
print "Child Pid $$ just read this: `$line'\n";
print $parent "Child Pid $$ is sending this\n";
close $parent;
exit;
}
In fact, some systems have historically implemented pipes as two
half-closed ends of a socketpair. They essentially define
pipe($reader, $writer) this way:
socketpair($reader, $writer, AF_UNIX, SOCK_STREAM, PF_UNSPEC);
shutdown($reader, 1); # no more writing for reader
shutdown($writer, 0); # no more reading for writer