写点什么

解读《深入理解计算机系统 (CSAPP)》第 10 章系统级 IO

  • 2022 年 7 月 14 日
  • 本文字数:1911 字

    阅读完需:约 6 分钟

前言:📫 作者简介:小明java问道之路,专注于研究计算机底层,就职于金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的设计和架构📫 🏆 Java 领域新星创作者、阿里云专家博主、华为云享专家🏆🔥 如果此文还不错的话,还请👍关注点赞收藏三连支持👍一下博主哦

本文导读

一切都是文件,都可以用 “”打开 open –> 读写 write/read –> 关闭 close” 模式来操作。输入/输出(I/O) 是指主存和外部设备(如磁盘,终端,网络)之间拷贝数据过程。

高级别 IO 有 C 提供标准 IO 库 I/O 函数 scanf 和 printf ,C++重载操作符<<和>>,Liunx 系统使用内核提供的系统级 I/O 函数实现……大多数时候高级别 I/O 函数都运行良好,为什么我们还要学 Unix I/O:了解 Unix I/O 将帮助你理解其他的系统概念。要深入理解其他概念,必须理解 I/O。标准 I/O 库没有提供读取文件元数据的方式(如文件大小或文件创建时间)。


重点解读:

一、Unix I/O

一个 Liunx 文件就是一个 m 个字节的序列:B0 B1 ……B(m-1),所有 I/O 设备都被模型化为文件。而所有的输入和输出都被当做相应文件的读和写。这种将设备优雅地映射成文件,允许 Unix 内核引出一个简单,低级的应用接口。叫做 Unix I/O。

打开文件:应用程序要求内核打开文件,内核返回一个小的非负整数,叫做描述符,它在后续对此文件的所有操作中标识这个文件。内核记录打开文件的所有信息,应用程序只需要记住描述符。

改变当前文件位置:对于每个打开的文件,内核保持一个文件位置 k,初始为 0。文件位置即是从文件开头起始的字节偏移量。应用程序通过执行 seek 操作,显式地设置文件位置 k 。

读写文件:一个读操作就是从文件拷贝 n 个字节到内存,然后将 k 增加到 k+n。给定一个大小为 m 字节的文件,当 k>=m 时执行读操作会触发一个称 为 end-of-file(EOF)的条件。应用程序能检测到这个条件(或者说信号?),文件结尾并没有这样的符号。写操作就是从存储器拷贝 n 个字节到一个文件,从当前文件位置 k 开始,然后更新 k。 

关闭文件:当应用程序完成了文件的访问,通知内核关闭文件。作为响应内核释放文件打开时创建的数据结构。将描述符恢复到可用的描述符池中。无论一个进程因为何种原因被关闭,内核会关闭所有它打开的文件,并释放他们的内存资源。

二、打开和关闭文件

进程是通过调用 open 函数来打开一个已存在的文件或者创建一个新文件的


三、读和写文件

调用 read 和 write 完成输入输出


四、读取文件元数据

应用程序能够通过调用 stat 和 fstate 函数,检索到关于文件的信息(有时也称为文件的元数据(metadata))


五、读取目录内容

应用程序可以用 readdir 系列函数读取目录的内容


六、共享文件

内核有三个相关的数据结构来表示打开的文件:描述符表(descriptor table):每个进程都有它独立的描述符表。它的表项是由进程打开的文件描述符来索引的。每个打开的描述符表项指向文件表的一个表项。

文件表(file table):打开文件的集合是由一张文件表表示的。所有的进程共享这张表。每个文件表项的部分组成,包括当前的文件位置、引用计数(reference count)即当前指向该表项的描述符项数)、以及一个指向 v-node 表中对应表项的指针。关闭一个描述符会减少相应文件表表项中的引用计数。当引用计数变为 0。内核会删除这个文件表表项。

v-node 表:所有的进程共享这张表。每个表项包含 stat 结构的大多数信息。包括 st_mode、st_size。

重定向标准输出之后的内核数据结构

七、标准 I/O

ANSI C 定义了一组高级输入输出函数,称为标准 I/O 库。这个库(libc)提供了,打开和关闭文件的函数(fopen 和 fclose)、读和写字节(fread 和 fwrite)、读和写字符串的函数(fgets 和 fputs)、以及复杂的格式化 I/O 函数 (scanf 和 printf)

我们该使用哪些 I/O 函数

小结

1、Linux 提供了少量的基于 Unix I/O 模型的系统级函数,它们允许应用程序打开、关闭、读和写文件提取文件的元数据,以及执行 I/O 重定向。2、Linux 的读和写操作会出现不足值,应用程序必须能正确地预计和处理这种情况。3、应用程序不应直接调用 UnixI/O 函数,而应该使用 RIO 包,RIO 包通过反复执行读写操作,直到传送完所有的请求数据,自动处理不足值。4、Linux 内核使用三个相关的数据结构来表示打开的文件。描述符表中的表项指向打开文件表中的表项,而打开文件表中的表项又指向 v-node 表中的表项。每个进程都有它自己单独的描述符表,而所有的进程共享同一个打开文件表和 v-node 表。理解这些结构的一般组成就能使我们清楚地理解文件共享和 I/O 重定向。5、标准 I/O 库是基于 Unix I/O 实现的,并提供了一组强大的高级 I/O 例程。对于大多数应用程序而言,标准 I/O 更简单,是优于 UnixI/O 的选择。然而,因为对标准 I/O 和网络文件的一些相互不兼容的限制,UnixI/O 比之标准 I/O 更该适用于网络应用程序。

发布于: 刚刚阅读数: 5
用户头像

物有本末,事有终始。知所先后,则近道矣 2020.03.20 加入

🏆CSDNJava领域新星创作者、阿里云专家博主、华为云享专家 📫就职某大型金融互联网公司高级研发工程师 👍注于研究计算机底层、算法和数据结构

评论

发布
暂无评论
解读《深入理解计算机系统(CSAPP)》第10章系统级IO_unix_小明Java问道之路_InfoQ写作社区