3.9 I/O Efficiency
Using only the read and write functions, Program 3.3 copies a file. The following caveats apply to Program 3.3:
-
It reads from standard input and writes to standard output. This assumes that these have been set up by the shell before this program is executed. Indeed, all normal Unix shells provide a way to open a file for reading on standard input and to create (or rewrite) a file on standard output. This prevents the program from having to open the input and output files.
-
Many applications assume that standard input is file descriptor 0 and standard output is file descriptor 1. In this example we use the two defined names STDIN_FILENO and STDOUT_FILENO from <unistd.h>.
Program 3.3 Copy standard input to standard output.
#include "ourhdr.h" #define BUFFSIZE 8192 int main(void) { int n; char buf[BUFFSIZE]; while ( (n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) if (write(STDOUT_FILENO, buf, n) != n) err_sys("write error"); if (n < 0) err_sys("read error"); exit(0); }
-
The program doesn't close the input file or output file. Instead it uses the fact that whenever a process terminates, Unix closes all open file descriptors.
-
This example works for both text file and binary files, since there is no difference between the two to the Unix kernel.
One question we haven't answered, however, is how we chose the BUFFSIZE value. Before answering that, let's run the program using different values for BUFFSIZE. In Figure 3.1 we show the results for reading a 1,468,802 byte file, using 18 different buffer sizes.
Figure 3.1. Timing results for reading with different buffer sizes.
The file was read using Program 3.3 with standard output redirected to /dev/null. The filesystem used for this test was a Berkeley fast filesystem with 8192-byte blocks. (The st_blksize, which we describe in Section 4.12, is 8192.) This accounts for the minimum in the system time occurring at a BUFFSIZE of 8192. Increasing the buffer size beyond this has no effect.
We'll return to this timing example later in the text. In Section 3.13 we show the effect of synchronous writes, and in Section 5.8 we compare these unbuffered I/O times with the standard I/O library.