mirror of https://github.com/mkerrisk/man-pages
Relocated example program and made its .SH title "EXAMPLE".
This commit is contained in:
parent
0784f93ce4
commit
3618596929
|
@ -342,7 +342,162 @@ A simple example of the use of
|
|||
can be found in the
|
||||
.BR select (2)
|
||||
manual page.
|
||||
.SH PORT FORWARDING EXAMPLE
|
||||
.SS Select Law
|
||||
Many people who try to use
|
||||
.BR select ()
|
||||
come across behavior that is
|
||||
difficult to understand and produces non-portable or borderline
|
||||
results.
|
||||
For instance, the above program is carefully written not to
|
||||
block at any point, even though it does not set its file descriptors to
|
||||
non-blocking mode at all (see
|
||||
.BR ioctl (2)).
|
||||
It is easy to introduce
|
||||
subtle errors that will remove the advantage of using
|
||||
.BR select (),
|
||||
hence I will present a list of essentials to watch for when using the
|
||||
.BR select ()
|
||||
call.
|
||||
.TP
|
||||
\fB1.\fP
|
||||
You should always try to use
|
||||
.BR select ()
|
||||
without a timeout.
|
||||
Your program
|
||||
should have nothing to do if there is no data available.
|
||||
Code that
|
||||
depends on timeouts is not usually portable and is difficult to debug.
|
||||
.TP
|
||||
\fB2.\fP
|
||||
The value \fInfds\fP must be properly calculated for efficiency as
|
||||
explained above.
|
||||
.TP
|
||||
\fB3.\fP
|
||||
No file descriptor must be added to any set if you do not intend
|
||||
to check its result after the
|
||||
.BR select ()
|
||||
call, and respond
|
||||
appropriately.
|
||||
See next rule.
|
||||
.TP
|
||||
\fB4.\fP
|
||||
After
|
||||
.BR select ()
|
||||
returns, all file descriptors in all sets
|
||||
should be checked to see if they are ready.
|
||||
.\" mtk, May 2006: the following isn't really true.
|
||||
.\" Any file descriptor that is available
|
||||
.\" for writing \fImust\fP be written to, and any file descriptor
|
||||
.\" available for reading \fImust\fP be read, etc.
|
||||
.TP
|
||||
\fB5.\fP
|
||||
The functions
|
||||
.BR read (2),
|
||||
.BR recv (2),
|
||||
.BR write (2),
|
||||
and
|
||||
.BR send (2)
|
||||
do \fInot\fP necessarily read/write the full amount of data
|
||||
that you have requested.
|
||||
If they do read/write the full amount, its
|
||||
because you have a low traffic load and a fast stream.
|
||||
This is not
|
||||
always going to be the case.
|
||||
You should cope with the case of your
|
||||
functions only managing to send or receive a single byte.
|
||||
.TP
|
||||
\fB6.\fP
|
||||
Never read/write only in single bytes at a time unless your are really
|
||||
sure that you have a small amount of data to process.
|
||||
It is extremely
|
||||
inefficient not to read/write as much data as you can buffer each time.
|
||||
The buffers in the example above are 1024 bytes although they could
|
||||
easily be made larger.
|
||||
.TP
|
||||
\fB7.\fP
|
||||
The functions
|
||||
.BR read (2),
|
||||
.BR recv (2),
|
||||
.BR write (2),
|
||||
and
|
||||
.BR send (2)
|
||||
as well as the
|
||||
.BR select ()
|
||||
call can return \-1 with
|
||||
.I errno
|
||||
set to \fBEINTR\fP,
|
||||
or with
|
||||
.I errno
|
||||
set to \fBEAGAIN\fP (\fBEWOULDBLOCK\fP).
|
||||
These results must be properly managed (not done properly
|
||||
above).
|
||||
If your program is not going to receive any signals then
|
||||
it is unlikely you will get \fBEINTR\fP.
|
||||
If your program does not
|
||||
set non-blocking I/O, you will not get \fBEAGAIN\fP.
|
||||
Nonetheless
|
||||
you should still cope with these errors for completeness.
|
||||
.TP
|
||||
\fB8.\fP
|
||||
Never call
|
||||
.BR read (2),
|
||||
.BR recv (2),
|
||||
.BR write (2),
|
||||
or
|
||||
.BR send (2)
|
||||
with a buffer length of zero.
|
||||
.TP
|
||||
\fB9.\fP
|
||||
If the functions
|
||||
.BR read (2),
|
||||
.BR recv (2),
|
||||
.BR write (2),
|
||||
and
|
||||
.BR send (2)
|
||||
fail
|
||||
with errors other than those listed in \fB7.\fP,
|
||||
or one of the input functions returns 0, indicating end of file,
|
||||
then you should \fInot\fP pass that descriptor to
|
||||
.BR select ()
|
||||
again.
|
||||
In the above example,
|
||||
I close the descriptor immediately, and then set it to \-1
|
||||
to prevent it being included in a set.
|
||||
.TP
|
||||
\fB10.\fP
|
||||
The timeout value must be initialized with each new call to
|
||||
.BR select (),
|
||||
since some operating systems modify the structure.
|
||||
.BR pselect ()
|
||||
however does not modify its timeout structure.
|
||||
.TP
|
||||
\fB11.\fP
|
||||
I have heard that the Windows socket layer does not cope with OOB data
|
||||
properly.
|
||||
It also does not cope with
|
||||
.BR select ()
|
||||
calls when no file
|
||||
descriptors are set at all.
|
||||
Having no file descriptors set is a useful
|
||||
way to sleep the process with sub-second precision by using the timeout.
|
||||
(See further on.)
|
||||
.SS Usleep Emulation
|
||||
On systems that do not have a
|
||||
.BR usleep (3)
|
||||
function, you can call
|
||||
.BR select ()
|
||||
with a finite timeout and no file descriptors as
|
||||
follows:
|
||||
.PP
|
||||
.nf
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 200000; /* 0.2 seconds */
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
.fi
|
||||
.PP
|
||||
This is only guaranteed to work on Unix systems, however.
|
||||
.SH EXAMPLE
|
||||
Here is an example that better demonstrates the true utility of
|
||||
.BR select ().
|
||||
The listing below is a TCP forwarding program that forwards
|
||||
|
@ -633,161 +788,6 @@ time, although it could easily be extended to do this with a linked list
|
|||
of buffers \(em one for each connection.
|
||||
At the moment, new
|
||||
connections cause the current connection to be dropped.
|
||||
.SS Select Law
|
||||
Many people who try to use
|
||||
.BR select ()
|
||||
come across behavior that is
|
||||
difficult to understand and produces non-portable or borderline
|
||||
results.
|
||||
For instance, the above program is carefully written not to
|
||||
block at any point, even though it does not set its file descriptors to
|
||||
non-blocking mode at all (see
|
||||
.BR ioctl (2)).
|
||||
It is easy to introduce
|
||||
subtle errors that will remove the advantage of using
|
||||
.BR select (),
|
||||
hence I will present a list of essentials to watch for when using the
|
||||
.BR select ()
|
||||
call.
|
||||
.TP
|
||||
\fB1.\fP
|
||||
You should always try to use
|
||||
.BR select ()
|
||||
without a timeout.
|
||||
Your program
|
||||
should have nothing to do if there is no data available.
|
||||
Code that
|
||||
depends on timeouts is not usually portable and is difficult to debug.
|
||||
.TP
|
||||
\fB2.\fP
|
||||
The value \fInfds\fP must be properly calculated for efficiency as
|
||||
explained above.
|
||||
.TP
|
||||
\fB3.\fP
|
||||
No file descriptor must be added to any set if you do not intend
|
||||
to check its result after the
|
||||
.BR select ()
|
||||
call, and respond
|
||||
appropriately.
|
||||
See next rule.
|
||||
.TP
|
||||
\fB4.\fP
|
||||
After
|
||||
.BR select ()
|
||||
returns, all file descriptors in all sets
|
||||
should be checked to see if they are ready.
|
||||
.\" mtk, May 2006: the following isn't really true.
|
||||
.\" Any file descriptor that is available
|
||||
.\" for writing \fImust\fP be written to, and any file descriptor
|
||||
.\" available for reading \fImust\fP be read, etc.
|
||||
.TP
|
||||
\fB5.\fP
|
||||
The functions
|
||||
.BR read (2),
|
||||
.BR recv (2),
|
||||
.BR write (2),
|
||||
and
|
||||
.BR send (2)
|
||||
do \fInot\fP necessarily read/write the full amount of data
|
||||
that you have requested.
|
||||
If they do read/write the full amount, its
|
||||
because you have a low traffic load and a fast stream.
|
||||
This is not
|
||||
always going to be the case.
|
||||
You should cope with the case of your
|
||||
functions only managing to send or receive a single byte.
|
||||
.TP
|
||||
\fB6.\fP
|
||||
Never read/write only in single bytes at a time unless your are really
|
||||
sure that you have a small amount of data to process.
|
||||
It is extremely
|
||||
inefficient not to read/write as much data as you can buffer each time.
|
||||
The buffers in the example above are 1024 bytes although they could
|
||||
easily be made larger.
|
||||
.TP
|
||||
\fB7.\fP
|
||||
The functions
|
||||
.BR read (2),
|
||||
.BR recv (2),
|
||||
.BR write (2),
|
||||
and
|
||||
.BR send (2)
|
||||
as well as the
|
||||
.BR select ()
|
||||
call can return \-1 with
|
||||
.I errno
|
||||
set to \fBEINTR\fP,
|
||||
or with
|
||||
.I errno
|
||||
set to \fBEAGAIN\fP (\fBEWOULDBLOCK\fP).
|
||||
These results must be properly managed (not done properly
|
||||
above).
|
||||
If your program is not going to receive any signals then
|
||||
it is unlikely you will get \fBEINTR\fP.
|
||||
If your program does not
|
||||
set non-blocking I/O, you will not get \fBEAGAIN\fP.
|
||||
Nonetheless
|
||||
you should still cope with these errors for completeness.
|
||||
.TP
|
||||
\fB8.\fP
|
||||
Never call
|
||||
.BR read (2),
|
||||
.BR recv (2),
|
||||
.BR write (2),
|
||||
or
|
||||
.BR send (2)
|
||||
with a buffer length of zero.
|
||||
.TP
|
||||
\fB9.\fP
|
||||
If the functions
|
||||
.BR read (2),
|
||||
.BR recv (2),
|
||||
.BR write (2),
|
||||
and
|
||||
.BR send (2)
|
||||
fail
|
||||
with errors other than those listed in \fB7.\fP,
|
||||
or one of the input functions returns 0, indicating end of file,
|
||||
then you should \fInot\fP pass that descriptor to
|
||||
.BR select ()
|
||||
again.
|
||||
In the above example,
|
||||
I close the descriptor immediately, and then set it to \-1
|
||||
to prevent it being included in a set.
|
||||
.TP
|
||||
\fB10.\fP
|
||||
The timeout value must be initialized with each new call to
|
||||
.BR select (),
|
||||
since some operating systems modify the structure.
|
||||
.BR pselect ()
|
||||
however does not modify its timeout structure.
|
||||
.TP
|
||||
\fB11.\fP
|
||||
I have heard that the Windows socket layer does not cope with OOB data
|
||||
properly.
|
||||
It also does not cope with
|
||||
.BR select ()
|
||||
calls when no file
|
||||
descriptors are set at all.
|
||||
Having no file descriptors set is a useful
|
||||
way to sleep the process with sub-second precision by using the timeout.
|
||||
(See further on.)
|
||||
.SS Usleep Emulation
|
||||
On systems that do not have a
|
||||
.BR usleep (3)
|
||||
function, you can call
|
||||
.BR select ()
|
||||
with a finite timeout and no file descriptors as
|
||||
follows:
|
||||
.PP
|
||||
.nf
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 200000; /* 0.2 seconds */
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
.fi
|
||||
.PP
|
||||
This is only guaranteed to work on Unix systems, however.
|
||||
.SH RETURN VALUE
|
||||
On success,
|
||||
.BR select ()
|
||||
|
|
Loading…
Reference in New Issue