# FILE I/O: THE UNIVERSAL I/O MODEL
We introduce the concept of a file descriptor, and then look at the system calls that constitute the so-called universal I/O model. These are the system calls that open and close a file, and read and write data.
## Overview
All system calls for performing I/O refer to open files using a file descriptor, a (usually small) nonnegative integer. File descriptors are used to refer to all types of open files, including pipes, FIFOs, sockets, terminals, devices, and regular files. Each process has its own set of file descriptors.
By convention, most programs expect to be able to use the three standard file
descriptors listed in Table 4-1.
### 3 standard file descriptor
| File descriptor | POSIX name | stdio stream |
| ----------------| ---------- | ------------ |
| 0 | STDIN_FILENO | stdin |
| 1 | STDOUT_FILENO | stdout |
| 2 | STDERR_FILENO | stderr |
The following are the four key system calls for performing file I/O (programming languages and software packages typically employ these calls only indirectly, via I/O libraries):
### 6 general IO operation:
* open()
* read()
* write()
* close()
* lseek(): File holes
* ioctl()/unlocked_ioctl() and compat_ioctl()
## 4.2 Universality of I/O
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.
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 (Section 4.8), which provides an interface to features that fall outside the universal I/O model.
## 4.3 Opening a File: open()
## 4.4 Reading from a File: read()
## 4.5 Writing to a File: write()
## 4.6 Closing a File: close()
## 4.7 Changing the File Offset: lseek()
The file offset is set to point to the start of the file when the file is opened and is automatically adjusted by each subsequent call to read() or write() so that it points to the next byte of the file after the byte(s) just read or written. Thus, successive read() and write() calls progress sequentially through a file.
## 4.8 Operations Outside the Universal I/O Model: ioctl()
https://ithelp.ithome.com.tw/articles/10161100
## 4.9 Summary
In order to perform I/O on a regular file, we must first obtain a file descriptor using open(). I/O is then performed using read() and write(). After performing all I/O, we should free the file descriptor and its associated resources using close().
These system calls can be used to perform I/O on all types of files.
The ioctl() system call is a catchall for device and file operations that don’t fit into the standard file I/O model.