从Linux的层次角度来说,在用户空间是存在这样的概念的,这个概念是存在内核空间的,而且是针对打开的文件的!
进程表
也称进程控制块PCB,由结构task_struct
所定义的数据结构。task_struct
结构体专门用于存放进程在运行过程中,所涉及到的所有与进程相关的信息。这个结构体的成员项非常多,多达近300个。其中,文件描述符表就被包含在了task_struct
结构体当中。在进程运行结束后,进程表所占用的内存空间,会被释放。
三种数据结构
从Linux的层次角度来说,这个概念是存在内核空间的,而且是针对打开的文件的!
内核用三种数据结构来描述一个打开的文件。
打开一个文件的内核数据结构图
文件描述符表:
open
打开文件后,会在进程的task_struct
结构体中,创建相应的结构体,用以存放打开文件的相关信息。对文件进行读写等操作时,会用到这些信息,这个数据结构就是我们要讲的文件描述符表
。
每个进程都有它独立的描述符表,它的表项是由进程打开的文件描述符来索引的。每个打开的文件描述符表项指向文件表
中的一个表项。
文件表
所有”打开的文件”的集合!
每个磁盘文件在打开时都会在内核中建立一个文件表项,内核为所有打开文件维持一张文件表。
每个文件表项包括:
- 文件状态标志:读、写、添写、同步、非阻塞等
- 当前文件偏移量
- 指向该文件v节点表项的指针
文件状态标志
文件状态标志就是open文件时指定的O_RDONLY
、O_WRONLY
、O_RDWR
等操作权限。open打开文件成功后,就会将文件状态标志保存到文件表中。在对文件执行操作时,会先检查文件状态标志,看看有没有操作权限,然后再去操作文件。
文件偏移量
文件当前读写位置与文件开始位置的距离(字节数)。
函数指针
在read
、write
等操作文件时,会根据底层具体情况的不同,调用不同的函数来实现读写。在V节点里面保存了这些不同函数的函数指针,方便调用。
v-node
v-node
在(v-node table
) 。同文件表一样,所有的进程共享这张v-node表
。
每个打开文件(或设备)都有个v节点结构。
v节点包含:
- 文件类型
- 对此文件进行各种操作的函数指针。
对于大多数文件,v节点还包含了该文件的i节点(索引节点)。
i节点包含:
- 文件的所有者
- 文件长度
- 文件所在设备
- 指向文件实际在磁盘上所在位置的指针。
文件长度
记录了文件当前的长度,文件长度是动态更新的。
注:
- 在文件表或者v索引节点中都有索引计数 (即当前指向该表项的描述符表项数),引用计数为0的时候就可以收回此表项
- fork后父子进程各自的每一个打开的文件描述符共享同一个文件表项