csapp第十章——系统级IO
系统级I/O
输入与输出 (I/O) 是在主存和外部设备(例如磁盘驱动器、终端和网络)之间复制数据的过程。
UNIX I/O
- 所有的设备(例如网络、磁盘和终端)都被模型化为文件,而所有的输入和输出都被当作对相应文件的读和写来执行。
打开文件
。一个应用程序通过要求内核打开相应的文件,来宣告它想要访问一个设备。内核返回一个小的非负整数,叫做描述符
,它在后续对此文件的所有操作中标识这个文件。内核记录有关这个打开文件的所有信息。应用程序只需记住这个描述符。- Linux shell 创建的每个进程开始时都有三个打开的文件:
1 |
|
改变当前的文件位置
。对于每个打开的文件,内核保持着一个文件位置 k, 是从文件开头起始的字节偏移量。读写文件
。当读操作文件位置k大于文件大小时,触发 end-of-file(EOF) 的条件,应用程序能检测到这个条件。但是在文件结尾没有明确的“EOF”符号。关闭文件
。当应用完成了对文件的访问之后,它就通知内核关闭这个文件。作为响应,内核释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中。
文件
文件类型:
普通文件 (regular file)
包含任意数据 。分为文本文件 (text file) 和二进制文件 (binary file) , 对内核而言,文本文件和二进制文件没有区别。目录(directory)
是包含一组链接 (link)的文件,其中每个链接都将一个文件名(filename) 映射到一个文件,这个文件可能是另一个目录。每个目录至少含有两个条目:“.”是到该目录自身的链接,以及”.. “是到目录层次结构中父目录的链接。- 套接字 (socket) 是用来与另一个进程进行跨网络通信的文件 。
- 命名通道 (named pipe) 、符号链接 (symbolic link), 以及字符和块设备 (character and block device) ·······
Linux 内核将所有文件都组织成一个目录层次结构 (directory hierarchy)
, 由名为/(斜杠)的根目录确定。系统中的每个文件都是根目录的直接或间接的后代。
路径名可分为:绝对路径名(absolute pathname)
和相对路径名(relative pathname)
打开和关闭文件
1 |
|
读和写文件
1 |
|
RIO包
- 无缓冲的输入输出函数
- 带缓冲的输入函数
//TODO
读取文件元数据
- 通过调用
stat
和fstat
函数检索元数据
1 |
|
读取目录内容
1 |
|
共享文件
内核用三个数据结构描述打开的文件:
描述符表 (descriptor table)
。每个进程都有它独立的描述符表。文件表 (file table)
。打开文件的集合是由一张文件表来表示的,所有的进程共享这张表。内核不会删除这个文件表表项,直到它的引用计数为零。v-node (v-node table)
同文件表一样,所有的进程共享。
- 当以同一个
filename
调用open
两次
- 父子进程共享相同的打开文件表集合
I/O重定向
>
重定向操作符dup2(int oldfd,int newfd)
复制描述符表表项 oldfd 到描述符表表项 newfd, 覆盖描述符表表项 newfd 以前的内容。
标准I/O
- fopen()和fclose()
- fread()和fwrite()
- fgets()和fputs()
标准I/O将打开的文件模型化为一个流(相当于一个指向FILE类型的指针)
每个ANSI C 程序开始时都有三个打开的流stdin 、stdout和stderr, 分别对应于标准输入、标准输出和标准错误:
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Randolfluo's blog!