10.1 Unix I/O
一个Unix文件就是一个m个字节的序列,所有的I/O设备都被模型化为文件,所有的输入和输出都被当做对应的文件的读和写操作来执行。
- 打开文件
一个应用程序通过要求内核打开相应的文件,来宣告他想要访问一个I/O设备,内核返回一个小的非负整数叫做描述符,他在后续对此文件的所有操作中标识这个文件,内核记录有关这个打开文件的所有信息,应用程序只需记住这个描述符。
Unix外壳创建的每个进程开始时都有三个打开的文件:标准输入(描述符为0),标准输出(1),标准错误(2)。
- 改变当前的文件位置
对于每个打开的文件,内核保持着一个文件位置k,初始为0,这个文件位置时从文件开头起始的字节偏移量,应用程序能够通过执行seek操作,显式地设置文件的当前位置为k。
- 读写文件
一个读操作就是从文件拷贝n>0个字节到存储器,从文件位置k开始,然后将k增加到k+n。给定一个大小为m字节的文件,当k≥m时执行读操作会触发一个EOF条件,检测到这个条件。类似的写操作就是存存储器拷贝n>0个字节到一个文件,从当前文件位置k开始然后更新k。
- 关闭文件
当应用完成了对文件的访问之后,他就通知内核关闭这个文件,作为响应,内核释放文件打开是创建的数据结构,并将这个描述符恢复到可用的描述符池中,无论一个进程因为何种原因终止时,内核都会关闭所有打开的文件并释放他们的存储器资源。
10.2 打开和关闭文件
flags参数指明进程如何访问文件
- O_RDONLY:只读
- O_WRONLY:只写
- O_RDWR:可读可写
flags参数也可以是一个或者更多位掩码的或:
- O_CREAT:如果文件不存在,就创建他的一个截断的空文件
- O_TRUNC:如果文件已经存在就截断它
- O_APPEND:在每次写操作前,设置文件位置到文件的结尾处
10.3 读和写文件
- read函数
从描述符为fd的当前文件位置拷贝最多n个字节到存储器位置buf。返回值-1表示一个错误,而返回值0表示EOF。否则,返回值表示的是实际传送的字节数量。
- write函数
从存储器位置buf拷贝至多n个字节到描述符fd的当前文件位置。返回值要么为-1要么为写入的字节数目。
- lseek函数
显示的修改当前文件位置。
- 出现不足值的情况
a.读时遇到EOF。此时read返回0来发出EOF信号。
b.从终端读文本行。如果打开文件是与终端相关联,那么每个read函数将以此传送一个文本行,返回的不足值等于文本行的大小。
c.读和写网络套接字。可能会出现阻塞现象。
10.4 用RIO包健壮地读写
- 提供了两类不同的函数:
无缓冲的输入输出函数 直接在存储器和文件之间传送数据。
带缓冲的输入函数
- rio_readn函数
1.从描述符fd的当前文件位置最多传送n个字节到存储器位置usrbuf。
2.遇到EOF只能返回一个不足值。
- rio_writen函数
1.从位置usrbuf传送n个字节到描述符fd。
2.绝不会返回一个不足值。
- 对同一个描述符,可以任意交错地调用rio_readn和rio_writen。
- 编写计算文本文件中文本行的数量如何实现?
1.read函数,一次一个字节从文件传送到用户存储器,检查每个字节来查找换行符。(效率低)
2.rio_realineb包装函数,从一个内部读缓冲区拷贝一个文本行,当缓冲区变空时,会自动调用read重新填满缓冲区。
- rio_realineb
1.从文件rp读出一个文本行,将它拷贝到存储器位置usrbuf,并用空字符结束这个文本行。
2.最多读maxlen-1个字节,余下的一个字符留给结尾的空字符串。
10.5 读取文件元数据
元数据:应用程序能够通过调用stat和fstat函数,检索到关于关于文件的信息,如创建时间,修改时间,metadata。
-
#include <unistd.h> #include <sys/stat.h> int stat(const char *filename, struct stat *buf); int fstat(int fd, struct stat *buf); 返回: 若成功则为0,若出错则为-1.
Stat函数以一个文件名作为输入,ftast以文件描述符作为输入。
- 函数是线程安全的:它在同一个描述符上可以被交替地调用。
10.6 共享文件
- 对于内核而言,文件文件和二进制文件毫无区别。
- 共享文件
内核用三种相关的数据结构来表示打开的文件。
1)描述符表:它的表项由进程打开的文件描述符来索引的。每个打开的描述符表项指向文件表中的一个选项。
2)文件表:打开文件的集合是一张文件表来表示的,所有的进程共享这张表。包括当前的文件位置、引用计数以及一个指向v-node表中对应表项的指针。
3)v-node表:同文件表一样,所有的进程共享这张v-node表。每个表项包含stat结构中的大部分信息,包括st_mode和st_size成员。
10.7 I/O重定向
unix>LS>foo.txt
使外壳加载和执行ls程序,将标准输出定向到磁盘文件
遇到的问题及解决办法:
unix提供了少量的系统级函数,它们允许用用程序打开、关闭、读和写文件,提取文件的元数据,以及执行I/O重定向,unix的读和写操作会出现不足值,出现此类情况,书上说使用RIO包,RIO包通过反复执行读写操作,其会自动处理不足值。但是在我的电脑系统上并没有自动处理该不足值
参考资料:《深入理解计算机中的 csapp,h和csapp.c》 http://www.cnblogs.com/LZYY/p/3423594.html
http://www.cnblogs.com/lhc-java/p/4941254.html