ptg10805159
Section 3.15 ioctlFunction 87
row in Figure3.13, but since theO_SYNCflag isn’t having the intended effect, the last
rowbehaves the same way as the fifth row.
Figure3.14 shows timing results for the same tests run on Mac OS X 10.6.8, which
uses theHFSfile system. Note that the times match our expectations: synchronous
writes arefar moreexpensive than delayed writes, and usingfsyncwith synchronous
writes makes very little difference. Note also that adding a call tofsyncat the end of
the delayed writes makes little measurable difference. It is likely that the operating
system flushed previously written data to disk as we werewriting new data to the file,
so by the time that we calledfsync,very little work was left to be done.
User CPU System CPU Clock time
Operation (seconds) (seconds) (seconds)
writeto/dev/null 0.14 1.02 5.28
normalwriteto disk file 0.14 3.21 17.04
writeto disk file withO_SYNCset 0.39 16.89 60.82
writeto disk followed byfsync 0.13 3.07 17.10
writeto disk withO_SYNCset followed byfsync 0.39 18.18 62.39
Figure 3.14 Mac OS XHFStiming results using various synchronization mechanisms
Comparefsyncandfdatasync,both of which update a file’s contents when we
say so, with theO_SYNCflag, which updates a file’s contents every time we write to the
file. The performance of each alternative will depend on many factors, including the
underlying operating system implementation, the speed of the disk drive, and the type
of the file system.
With this example, we see the need for fcntl.Our program operates on a
descriptor (standardoutput), never knowing the name of the file that was opened on
that descriptor.Wecan’t set theO_SYNCflag when the file is opened, since the shell
opened the file. Withfcntl, we can modify the properties of a descriptor,knowing
only the descriptor for the open file. We’ll see another need forfcntlwhen we
describe nonblocking pipes (Section 15.2), since all we have with a pipe is a descriptor.
3.15 ioctl Function
Theioctlfunction has always been the catchall for I/O operations. Anything that
couldn’t be expressed using one of the other functions in this chapter usually ended up
being specified with anioctl.Terminal I/O was the biggest user of this function.
(When we get to Chapter 18, we’ll see that POSIX.1 has replaced the terminal I/O
operations with separate functions.)
#include <unistd.h> /* System V */
#include <sys/ioctl.h> /* BSD and Linux */
int ioctl(intfd,int request,...);
Returns:−1 on error,something else if OK