输入/输出(I/O)是在主存(memory)和外部设备之间拷贝数据的过程。输入数据是从I/O设备拷贝数据到主存,输出数据是从主存拷贝数据到I/O设备。
10.1 Unix I/O
一个Linux文件就是一个m个字节的序列:B0,B1,...,Bk,...,Bm−1
所有的I/O设备都被模型化为文件,而所有的输入和输出都被当作对相应文件的读和写来执行。Linux内核使用一个简单、低级的应用接口即Unix I/O来统一且一致的执行所有的输入和输出:
- 打开文件。一个应用程序通过要求内核打开相应的文件,内核返回一个小的非负整数,称为描述符。内核记录有关这个打开文件的所有信息,应用程序只需记住这个描述符。
- Linux shell创建的每个进程开始时都有三个打开的文件:标准输入(描述符为0)、标准输出(描述符为1)和标准错误(描述符为2)。
- 改变当前的文件位置。对于每个打开的文件,内核保持着一个文件位置k,初始为0。这个文件位置是从文件开头起始的字节偏移量。应用程序能够通过执行seek操作,显示地设置文件的当前位置为k。
- 读写文件。一个读操作就是从文件复制n>0个字节到内存,从当前文件位置k开始,然后将k增加到k+n。给定一个大小为m字节的文件,当k≥m时执行读操作会触发一个称为end-of-file(EOF)的条件,应用程序能检测到这个条件。在文件结尾处并没有明确的"EOF符号"。类似的,写操作就是从内存复制n>0个字节到一个文件,从当前文件位置k开始,然后更新k。
- 关闭文件。当应用完成了对文件的访问之后,它就通知内核关闭这个文件。作为响应,内核释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中。无论一个进程因为何种原因终止时,内核都会关闭所有打开的文件并释放它们的内存资源。
10.2 文件
每个Linux文件都有一个类型(type)来表明它在系统中的角色:
- 普通文件(regular file)包含任意数据。
- 目录(directory)是包含一组链接(link)的文件,其中每个链接都将一个文件名映射到一个文件。每个目录至少包含两个条目:
.是到该目录自身的链接,以及..是到父目录(parent directory)的链接。
- 套接字(socket)是用来与另一个进程进行跨网络通信的文件。
其他文件类型包含命名管道(named pipe)、符号链接(symbolic link)等。
Linux内核将所有文件都组织成一个目录层次结构(directory hierarchy),由名为/的根目录确定。下图显示了Linux系统的目录层次结构的一部分。

