Recipe 7.9 Opening and Closing File Descriptors by Number
7.9.1 Problem
You know which
file descriptors you'd like to do I/O on, but Perl requires
filehandles, not descriptor numbers.
7.9.2 Solution
To open the file descriptor, supply
open with "<&=" or
"<&" as the part of the file access mode,
combined with a directional arrow:
open(FH, "<&=", $FDNUM) # open FH to the descriptor itself
open(FH, "<&", $FDNUM); # open FH to a copy of the descriptor
Or use
the IO::Handle module's new_from_fd class method:
use IO::Handle;
$fh = IO::Handle->new_from_fd($FDNUM, "r");
To close
a file descriptor by number, either use the
POSIX::close function or open it first as shown
previously.
7.9.3 Discussion
Occasionally you have a file descriptor but no filehandle. Perl's I/O
system uses filehandles instead of file descriptors, so you have to
make a new filehandle from an already open file descriptor. The
"<&", ">&", and
"+<&" access modes to
open do this for reading, writing, and updating,
respectively. Adding an equals sign to these—making them
"<&=", ">&=", and
"+<&="—is more parsimonious of file
descriptors and nearly always what you want. That's because the
underlying implementation of Perl's open statement
uses only a C-level fdopen(3) function from the
C library, not a dup2(2) syscall that calls the
kernel.
The new_from_fd IO::Handle object method is
equivalent to:
use IO::Handle;
$fh = new IO::Handle;
$fh->fdopen($FDNUM, "r"); # open fd 3 for reading
Here's how you'd open file descriptors that the MH mail system feeds
its child processes. It identifies them in the environment variable
MHCONTEXTFD:
$fd = $ENV{MHCONTEXTFD};
open(MHCONTEXT, "<&=", $fd) or die "couldn't fdopen $fd: $!";
# after processing
close(MHCONTEXT) or die "couldn't close context file: $!";
Closing a file descriptor by number is even rarer. If you've already
opened a filehandle for the file descriptor you want to close, simply
use Perl's close function on the filehandle. If
don't have a filehandle for that file descriptor, the
POSIX::close function closes a file descriptor by
number:
use POSIX;
POSIX::close(3); # close fd 3
7.9.4 See Also
The open function in
perlfunc(1) and in Chapter 29 of
Programming Perl; the documentation for the
standard POSIX and IO::Handle modules (also in Chapter 32 of
Programming Perl); your system's
fdopen(3) manpages
|