home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  

3.2.135 select (ready file descriptors)









The four-argument select operator is totally unrelated to the previously described operator. This operator is for discovering which (if any) of your file descriptors are ready to do input or output, or to report an exceptional condition. (This helps you avoid having to do polling.) It calls the select (2) system call with the bitmasks you've specified, which you can construct using fileno and vec , like this:

$rin = $win = $ein = "";
vec($rin, fileno(STDIN), 1) = 1;
vec($win, fileno(STDOUT), 1) = 1;
$ein = $rin | $win;

If you want to select on many filehandles you might wish to write a subroutine:

sub fhbits {
    my @fhlist = @_;
    my $bits;
    for (@fhlist) {
        vec($bits, fileno($_), 1) = 1;
    return $bits;
$rin = fhbits(qw(STDIN TTY MYSOCK));

If you wish to use the same bitmasks repeatedly (and it's more efficient if you do), the usual idiom is:

($nfound, $timeleft) =
    select($rout=$rin, $wout=$win, $eout=$ein, $timeout);

Or to block until any file descriptor becomes ready:

$nfound = select($rout=$rin, $wout=$win, $eout=$ein, undef);

The $wout=$win trick works because the value of an assignment is its left side, so $wout gets clobbered first by the assignment, and then by the select , while $win remains unchanged.

Any of the bitmasks can also be undef . The timeout, if specified, is in seconds, which may be fractional. (A timeout of 0 effects a poll.) Not many implementations are capable of returning the $timeleft . If not, they always return $timeleft equal to the supplied $timeout .

One use for select is to sleep with a finer resolution than sleep allows. To do this, specify undef for all the bitmasks. So, to sleep for (at least) 4.75 seconds, use:

select undef, undef, undef, 4.75;

(On some non-UNIX systems this may not work, and you may need to fake up at least one bitmask for a valid descriptor that won't ever be ready.)

Mixing buffered I/O (like read or <HANDLE> ) with four-argument select is asking for trouble. Use sysread instead.