COHERENT manpages

This page displays the COHERENT manpage for select() [Check if devices are ready for activity].

List of available manpages
Index


select() -- General Function (libsocket)

Check if devices are ready for activity
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
int select(nfds, readfds, writefds, exceptfds, timeout)
int nfds;
fd_set *readfds, *writefds, *exceptfds;
struct timeval *timeout;

The function  select() examines file  descriptors, and tells  you which are
ready for a given type of  activity.  select() can be used with descriptors
for  sockets, pipes,  and  most character  devices  including the  console,
serial terminals  connected via the  asy driver, and  pseudoterminals using
the pty driver.

readfds,  writefds, and  exceptfds each  gives the address  of a  a bit-map
whose bits correspond to the  file descriptors of the sockets that interest
you.  Respectively, these arguments identify the sockets that may have data
to be read, those that to  which you wish to write data, and those that may
have an exception condition  pending.  (What an ``error condition'' may be,
is  described below.)  select() examines descriptors  zero through  nfds in
each  set and  checks whether  the  corresponding socket  is ready  for the
activity in question.   If the socket is not ready,  select() flips off the
bits that correspond to that socket.

Please note that although  readfds, writefds, and exceptfds each is pointer
to int, the bit-map it points  to can be longer than 32 bits.  You can, for
example, declare that these pointers points to an array of ints. The number
of file descriptors you can ask select() to examine limited by the manifest
constant FD_SETSIZE, which  is defined in header file <sys/select.h>.
COHERENT  sets this  constant to  256;  thus, if  you set  nfds to  a value
greater than 256, only the first 256 file descriptors will be examined.

If  you are  not  interested in  a  given activity,  set the  corresponding
pointer to  NULL.  For example, if  you are interested only  in reading and
writing, but not in exception handling, set exceptfds to NULL.

timeout gives  the address a timeval structure that  holds the maximum time
you are  willing to  wait for  the selection to  complete.  If it  is NULL,
select() waits indefinitely.

By manipulating  the value of timeout, you can  perform some useful tricks.
For example,  if you set to  zero the fields tv_sec  and tv_usec within the
timeval structure to  which timeout points, select() performs a nonblocking
poll of  the indicated devices; this is  demonstrated below.  Another trick
is to set field tv_usec within  timeout to a nonzero value, but set nfds to
zero.  This tells select() to examine no sockets, but to wait the specified
number of microseconds while not doing  it.  This lets you ``sleep'' for an
interval shorter  than is possible  through the system  call sleep(), whose
minimum delay is one second.

If all  goes well, select() returns  the number of sockets  that are ready.
If the time limit expires, it  returns zero.  If an error occurs, it leaves
all three  bit maps unmodified,  returns -1, and  sets errno to  one of the
following values:

EBADF
     A descriptor  set specifies an invalid  descriptor.  For example, this
     error  occurs if  one of  the file descriptors  does not  describes an
     ordinary file instead of a socket.

EINTR
     select() received a signal before the time limit expired and before it
     could finish examining the sockets.

EINVAL
     The time structure to  which timeout points contains invalid data: one
     of its components is negative or too large.

The following example code demonstrates how  to set up a socket and examine
it  with   select().  is  taken  from  a  program   written  by  Jon  Dhuse
(jdhuse@sedona.intel.com),  and  was slightly  modified  for clarity.   The
entire program appears in the Lexicon entry libsocket:

    int sd[2], rdfds[2], wrtfds[2], i;
    struct timeval timeout;
        ...

    /* create socket */
    sd = socket(AF_UNIX, SOCK_STREAM, 0);
        ...

    /* initialize the arrays of ints */
    for (i = 1; i < 2; i++)
        rdfs[i] = 0;
        wrtfds[i] = 0;
    }
        ...

    /* Check whether socket is ready */
    rdfds[0] = 1 << sd;   /* initialize bit map to check for reading */
    wrtfds[0] = 1 << sd;  /* initialize bit map to check for writing */
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;
    i = select(sd+1, rdfds, wrtfds, (int *)NULL, &timeout);
    if (i < 0)
          printf("select() returned error %d\n", errno);
    else {
        if (rdfds & (1 << sd)) /* check if socket has data */
            printf("socket has data to be read\n");
        if (wrtfds & (1 << sd)) /* check if socket can be written to */
            printf("data can be written to socket\n");
    }

Associated Macros

The header  file <sys/select.h>  defines the following  macros, which
are meant to help you manipulate sets of file descriptors:

FD_ZERO (&amp;fdset)
     Initialize the bit map fdset to zero.

FD_SET (fd, &amp;fdset)
     Turn on bit fd within the bit map fdset.

FD_CLR (fd, &amp;fdset)
     Turn off bit fd within the bit map fdset.

FD_ISSET (fd, fdset)
     This macro evaluates to a non-zero value if bit fd is turned on within
     fdset; otherwise, it evaluates to zero.

The behavior of  these macros is undefined if a  descriptor's value is less
than zero or greater than or equal to FD_SETSIZE.

Exception Conditions

As noted above,  the bit map exceptfds identifies sockets  that may have an
exception  condition pending.   As  of this  writing,  COHERENT defines  an
``exception condition'' to be one of the following:

POLLHUP
     A  hangup has  occurred, i.e.,  loss  of carrier  on a  modem line  or
     closure of the associated  master device when select() queries a slave
     pseudo-tty.

POLLNVAL
     The file  descriptor does not  correspond to  an open device.

See Also

accept(),
connect(),
libsocket,
poll(),
read(),
write()

Notes

The system  call poll() uses  a different calling  sequence to do  much the
same work as socket().