系统级I/O

这次主要是文件I/O:
在对文件进行读写操作前,需要先打开该文件。内核为每个进程维护一个打开文件的列表,该表被称为文件表(file table)。该表由一些叫做文件描述符(file descriptors)的非负整数进行索引。列表中的每项均包括一个打开文件的信息,其中包括一个指向文件备份inode内存拷贝的指针和元数据(例如文件位置和访问模式等)。用户空间和内核空间都把文件描述符作为每个进程的唯一cookies。打开一个文件返回一个文件描述符,接下来的操作(读写等等)则把文件描述符作为基本参数。

1、进程表:内核维护一张进程表,记录每一个进程项,进程项中维持了一张在该进程中所有的打开的文件描述符,每个文件描述符记录了问价描述符标志和文件表项。
2、文件表:内核维护一张文件表,用来记录所有的打开的文件表项。每个文件表项记录文件描述符状态标记、文件指针当前偏移量以及指向文件v节点所在地址的指针。
3、v节点表:内核位置一张v节点表,记录所有打开的v节点,v节包含v节点信息以及i节点信息,每一个打开的文件有一个v节点结构,v节点中包含的i节点(索引节点)记录了文件的详细信息,例如记录了文件的长度,在盘中的地址等具体信息。
进程之间对文件的管理就是通过这个三张表的关系层层连接。一个进程打开一个未打开的文件时候,就会生成产生文件描述符、文件表项一v节点结构,来记录这个文件的详细信息,如若另外一个进程打开与该进程相同的文件时候,则在另外一个进程中只会生成一个当前进程下的文件描述符和一个文件表项,但是是不会在生成v节点结构,一个打开的文件有且只有一个v节点结构,也就是两个进程的文件表项就会共用该v节点。最后给出一张图,帮助理解。如下图所示(打开文件的内核将数据结构):

系统级I/O
两个重要的函数:
#include <unistd.h>
int fcntl(int fiedes,int cmd,…/
int arg /);

//若成功则依赖于cmd,若出错则返回-1。
第三个参数可能是一个整数,也有可能是一个指向结构的指针。

close函数:
int close(int fd);
//@param fd 需要关闭文件的文件描述符

虽然说进程结束后,会自动关闭所有打开的文件描述符,但是还是希望程序员自己手动关闭。函数成功返回0,失败返回-1。

dup2函数:
int dup2(int oldfd, int newfd);
/*
这个函数就是复制oldfd到newfd
也就是说在进程的文件描述符表中,newfd的内容将会被oldfd替代系统级I/O
*/

open函数:
进程是通过调用open来打开一个已经存在的文件,或者创建一个不存在的文件的。
函数原型
*#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(char filename, int flags, mode_t mode);

参数解析
filename:一个文件路径,可以是相对路径,也可以是绝对路径
flags:它有两个可选信息