ptg10805159
Section 14.7 readnandwritenFunctions 523
In summary,weshould always try to use the fewest number of system calls
necessary to get the job done. If we arewriting small amounts of data, we will find it
less expensive to copy the data ourselves and use a singlewriteinstead of using
writev.Wemight find, however,that the performance benefits aren’t worth the extra
complexity cost needed to manage our own staging buffers.
14.7 readnandwriten Functions
Pipes, FIFOs, and some devices—notably terminals and networks—have the following
two properties.
- Areadoperation may return less than asked for,even though we have not
encountered the end of file. This is not an error,and we should simply continue
reading from the device. - Awriteoperation can return less than we specified. This may be caused by
kernel output buffers becoming full, for example. Again, it’s not an error,and
we should continue writing the remainder of the data. (Normally,this short
return from awriteoccurs only with a nonblocking descriptor or if a signal is
caught.)
We’ll never see this happen when reading or writing a disk file, except when the file
system runs out of space or we hit our quota limit and we can’t write all that we
requested.
Generally,when we read from or write to a pipe, network device, or terminal, we
need to take these characteristics into consideration. We can use the readn and
writenfunctions to read and writeNbytes of data, respectively,letting these functions
handle a return value that’s possibly less than requested. These two functions simply
callreadorwriteas many times as required to read or write the entireNbytes of
data.
#include "apue.h"
ssize_t readn(intfd,void *buf,size_tnbytes);
ssize_t writen(intfd,void *buf,size_t nbytes);
Both return: number of bytes read or written,−1 on error
We define these functions as a convenience for later examples, similar to the error-handling
routines used in many of the examples in this text. Thereadnandwritenfunctions arenot
part of any standard.
We callwritenwhenever we’rewriting to one of the file types that we mentioned,
but we callreadnonly when we know ahead of time that we will be receiving a certain
number of bytes. Figure14.24 shows implementations ofreadnandwritenthat we
will use in later examples.
Note that if we encounter an error and have previously read or written any data, we
return the amount of data transferred instead of the error.Similarly, if we reach the end