本篇博文仅列出本章中提到的标准函数,不会记录RIO包等手写函数。
打开和关闭文件
open()
1 |
|
open函数将filename转换为一个文件描述符,并且返回描述符数字。返回的描述符总是在进程中当前没有打开的最小描述符。flags参数指明了进程打算如何访问这个文件。
- O_RDONLY: 只读。
- O_WRONLY: 只写。
- O_RDWR: 可读可写。
flags参数也可以是一个或者更多位掩码的或,为写提供给一些额外的指示:
- O_CREAT: 如果文件不存在,就创建它的一个截断的(truncated)(空)文件。
- O_TRUNC: 如果文件已经存在,就截断它。
- O_APPEND: 在每次写操作前,设置文件位置到文件的结尾处。
1 | 在sys/stat.h中定义的访问权限位 |
close()
1 |
|
读和写文件(read和write)
1 |
|
读取文件元数据
应用程序能够通过调用stat和fstat函数,检索到关于文件的信息(有时也称为文件的元数据(metadata))。
1 |
|
stat函数以一个文件名作为输入,并填写一个stat数据结构中的各个成员。fstat是相似的,只不过是以文件描述符而不是文件名作为输入。
1 | /* Metadata returned by the stat and fstat functions */ |
st_size成员包含了文件的字节数大小,st_mode成员则编码了文件访问许可位和文件类型。Linux在sys/stat.h中定义了宏谓词来确定st_mode成员的文件类型:
- S_ISREG(m)。这是一个普通文件吗?
- S_ISDIR(m)。这是一个目录文件吗?
- S_ISSOCK(m)。这是一个网络套接字吗?
读取目录内容
1 |
|
函数opendir以路径名为参数,返回指向*目录流(directory stream)*的指针。流是对条目有序列表的抽象,在这里是指目录项的列表。
1 |
|
每次对readdir的调用返回的都是指向流dirp中下一个目录项的指针,或者,如果没有更多目录项则返回NULL。每个目录项都是一个结构,其形式如下:
1 | struct dirent { |
I/O重定向
1 |
|
dup2函数复制描述符表表项oldfd到描述符表表项newfd,覆盖描述符表表项newfd以前的内容。如果newfd已经打开了,dup2会在复制oldfd之前关闭newfd。
共享文件
内核用三个相关的数据结构来表示打开的文件:
- ***描述符表(descriptor table)。每个进程都有它独立的描述符表,它的表项是由进程打开的文件描述符来索引的。每个打开的描述符表项指向文件表*中的一个表项。
- ***文件表(file table)**。打开文件的集合是由一张文件表来表示的,所有的进程共享这张表。每个文件表的表项组成(针对我们的目的)包括当前的文件位置,引用计数(reference count)*(即当前指向该表项的描述符表项数),以及一个指向v-node表中对应表项的指针。关闭一个描述符会减少相应的文件表表项中的引用计数。内核不会删除这个文件表表项,直到它的引用计数为零。
- ***v-node表(v-node table)***。同文件表一样,所有的进程共享这张v-node表,每个表项包含stat结构中的大多数信息,包括st_mode和st_size成员。
本篇完。