One of the distinguishing features of the UNIX I/O model is the concept of universality of I/O. This means that the same four system calls—open(), read(), write(), and close()—are used to perform I/O on all types of files, including devices such as terminals. Consequently, if we write a program using only these system calls, that program will work on any type of file. For example, the following are all valid uses of the program in Example 4-1:
$ ./copy test test.old
Copy a regular file$ ./copy a.txt /dev/tty
Copy a regular file to this terminal$ ./copy /dev/tty b.txt
Copy input from this terminal to a regular file$ ./copy /dev/pts/16 /dev/tty
Copy input from another terminal
Universality of I/O is achieved by ensuring that each file system and device driver implements the same set of I/O system calls. Because details specific to the file system or device are handled within the kernel, we can generally ignore device-specific factors when writing application programs. When access to specific features of a file system or device is required, a program can use the catchall ioctl() system call (Operations Outside the Universal I/O Model: ioctl()), which provides an interface to features that fall outside the universal I/O model.