目录
12章 - 虚拟文件系统 - vfs的数据结构
与进程相关的文件
引入
进程有很多关于文件系统的字段,这些字段主要被存放在两个表中 -- fs_struct和files_struct
介绍
fs_struct
- 这个结构包含了与进程自身的文件系统状态相关的信息,比如当前工作目录、根目录等
- 它记录了进程在文件系统中的位置和一些全局的文件系统设置
files_struct
- 这个结构包含了与打开文件和文件描述符相关的信息,比如打开文件的列表、文件描述符等
- 这个结构主要用于跟踪进程打开的文件,以及这些文件的状态
fs_struct
介绍
存放了进程与文件系统之间相互作用时,必须要维护的数据
- 进程pcb中的fs字段指向该结构
- 我们也可以通过"/proc/进程pid"这个目录来查看上面的一部分信息(比如当前的工作目录)
files_struct
介绍
表示当前进程打开的文件
- 进程pcb中的files字段指向该结构
fd字段
介绍
它指向fd_array字段 -- 一个保存了文件对象指针的初始数组(大小是32个)
如果进程打开文件数>32
- 会分配一个更大的数组
- 用该数组的首地址更新fd字段,用数组新大小更新max_fds字段
文件描述符表
实际上,fd字段指向的这个数组就是我们平时说的文件描述符表
- 文件描述符就是数组的索引值
限制数量
重定向
而重定向的原理就是修改fd字段指向的数组内容
- 数组内不同的位置可以填充相同的指针
比如:2>&1 实际上就是将数组内[索引=2指向的数据] 修改为 与[索引=1]中相同的数据
open_fds字段
介绍
open_fds字段指向open_fds_init字段
文件描述符位图
- 通常用于跟踪进程已打开的文件描述符
- 它是一个位图数据结构,其中每个位(bit)表示一个文件描述符的状态(打开或关闭)
- 该位图可以动态扩容
与vfs中对象的关联
fget()
当内核内需要使用某个文件时,可以通过fget()函数获得该指定文件的文件对象
- 通过进程pcb拿到files结构体(files_struct)
- 然后再通过fd字段+fd来获取文件对象地址
- 拿到后,会将文件对象中的f_count字段+1(引用计数)
fput()
当内核内完成某个文件的使用时,通过调用fput()来减少该文件的引用计数
- 通过文件对象使f_count字段-1
- 如果f_count=0时(也就是没有进程在使用该文件),就需要进行删除文件
删除文件需要进行的操作
因为一个inode可以对应多个文件对象(多个进程打开同一文件)
- 所以如果其中某个文件对象被释放,就需要修改inode的引用计数
超级块中有一链表,存放了所有属于该文件类型的文件对象的指针
- 所以,需要将这个要被删除的文件对象从该链表中移除
文件对象是通过slab高速缓存分配的,当删除文件时,需要释放空间还给slab
因为一个目录项对象可以对应多个文件对象(硬链接)
- 所以需要减少目录项对象中的引用计数值
- 但至于为什么是文件系统描述符的目录项对象:
- 可能是因为这个文件系统描述符的结构中,存放了所有的目录项对象?用于管理他们
- 减少这里的引用值,有助于内核及时释放未被使用的目录项对象?
fget_light()和fput_light()
- 也就是需要先有[已经增加了文件对象中的引用计数]的前提