教材学习内容总结
·输入/输出(I/O)是在主存和外部设备之间拷贝数据的过程。
·输入操作:从I/O设备拷贝数据到主存
·输出操作:从主存拷贝数据到I/O设备
1、打开文件:一个应用程序想访问I/O设备时会要求内核打开相应的文件,内核返回一个小的非负整数,叫做描述符。
它在后续对此文件的所有操作中标识这个文件。内核记录有关这个文件的所有信息,应用程序只需记住描述符。
每个进程开始时都有三个打开的文件:标准输入(描述符为0)、标准输出(描述符为1)、标准错误(描述符为2)
2、改变当前的文件位置:对于每个打开的文件,内核保持着一个文件位置k,初始为0,文件位置是从文件开头起始的字节偏移量。
应用程序能够通过执行seek操作,显示的设置文件的当前位置为k。
3、读写文件:读操作是从文件拷贝n>0个字节到存储器,从当前位置k开始,将k增加到k+n
当k>=m时执行读操作会触发一个称为end-of-file(EOF)的条件,应用程序能检测到这个条件。
写操作就是从存储器拷贝n>0个字节到一个文件,从当前位置k开始,然后更新k。
4、关闭文件:当应用完成对文件的访问,会通知内核关闭文件。
作为响应,内核释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中。
无论进程因何种原因终止,内核都会关闭所有打开的文件并释放他们的存储器资源。
共享文件
内核用三个相关的数据结构来表示打开的文件
文件表:所有进程共享,表项组成包括当前文件位置、引用计数、一个指向v-node表中对应表项的指针。引用计数为0时,内核会删除这个文件表表项。
v-node表:所有进程共享,每个表项包含stat结构中的大多数信息。
标准I/O(高级输入输出函数)
fopen/fclose:打开和关闭文件
fread/fwrite:读和写字节
fgets/fputs:读和写字符串
scanf/printf:复杂格式化的I/O函数
标准I/O库将一个打开的文件模型化为一个流,一个流就是一个指向FILE类型的结构指针。
每个程序开始时都有三个打开的流:
(1)stdin:标准输入
(2)stdout:标准输出
(3)stderr:标准错误
RIO
•RIO包是一个I/O包,它会自动处理不足值,在容易出现不足值的应用中,RIO包提供了方便、健壮和高效的I/O。
•RIO读程序的核心是rio_read函数,该函数是Unix read函数的带缓冲的版本。当调用rio_read要求读n个字节时,读缓冲区内有rp→rio_cnt个未读的字节。如果缓冲区为空,那么会通过read再填满它。这个read调用收到一个不足值并不是错误,只不过是缓冲区填充了一部分。一旦缓冲区非空,rio_read就从读缓冲区拷贝n和rio→cnt中较小值个字节到用户缓冲区,并返回拷贝的字节数。