C programmers are used to deal with file I/O using the simple ``stream'' model provided by the standard I/O library bundled with every ANSI C compliant compiler. The functions of this library should be used in normal applications, since their definition in the ANSI standard makes programs using them portable across different architectures and operating systems. Moreover, input and output is performed efficiently through them, since they provide transparent buffering of data, with buffer sizes optimized taking into account the underlying machine characteristics and ``general purpose'' usage considerations. Also, they offer a simple I/O interface to the programmer, allowing him/her to think in terms of high-level data abstractions like streams, characters, numbers, and not of chunks of bytes instead.
However, it happens at least once in every programmer's life that elegance and high level issues like portability have to be sacrificed for sake of efficiency, and then a more direct dialogue betweem a program and the machinery it runs on is desiderable. Furthermore, the high level I/O library must eventually be implemented in terms of the lower level, more general facilities provided by an operating system, rising some delicate system design issues with which we'll deal at length later.
The UNIX system provides a set of system calls for relatively low level, block-oriented I/O and file management. The low level functions mantain for each process a table called the object reference table or, sometimes, the descriptor table. This table contains, among other things, information about all open files in use by the current process. Each open file is identified by its index in the table, and these indexes are called file descriptors. The file descriptors are small integers, in the range 0 to 20 or so, and should never be confused with streams (i.e. FILE) pointers, which are pointers to structures mantained by the stream-oriented functions
We will now examine some of the system calls for manipulating files. The prototypes and appropriate constant declarations for all them are in the sys/types.h, sys/file.h, sys/stat.h, unistd.h and fcntl.h, which should always be included from the sources that use them.