虚拟文件系统
VFS使得用户可以直接使用open,read,write这样的系统调用而无需考虑具体的文件系统和实际物理介质
四个主要的对象类型
- 超级块对象:代表一个具体的已安装的文件系统
- 索引节点inode对象:代表一个具体文件
- 目录项对象:代表一个目录项,是路径的一个组成部分
- 文件对象:代表由进程打开的文件
- 四个对象的联系:文件可以当作一个有序字节序,通过目录组织起来,目录好比一个文件夹,文件的相关信息放在inode,文件会有特定的属性属于某个文件系统,文件系统的控制信息放在超级块
超级块对象super_block
存储特定文件系统的信息,在磁盘中存在
- 通常对应存放在磁盘特定扇区中的文件系统超级块,即不同分区两个相同文件系统对应两个超级块
- 所有超级块对象用双向循环链表形式连接
索引节点对象inode
包含内核在操作文件或目录时需要的全部信息,对文件是唯一的,随文件存在而存在。索引节点是物理意义上的文件,记录的是物理上的属性,在磁盘上有对应的映像
- 必须在内存创建
- 在同一文件系统中,每个inode号都是唯一的
- 记录文件是否为脏
目录项对象dentry
为了方便查找,按名存取,引入了目录项。存放目录项(文件特定名称)和链接有关的信息。目录项是逻辑意义上的文件,描述的是文件逻辑上的属性,在磁盘上没有对应的映像
- 一个索引节点对象可能对应多个目录项对象
链接
- 软链接相当于一个快捷方式,是一个新的文件,里面存的是源文件的路径,可以跨文件系统创建,可以链接目录
- 硬链接是通过索引节点来链接,文件副本不占空间(因为索引节点和磁盘盘块对应,硬链接的文件是使用一个索引节点的),会增加索引节点的引用数,不可以跨文件系统创建,不可以链接目录
- 命令都是ln,软连接用参数-s
- 目录问题:硬链接在操作系统遍历目录时会有循环问题,比如/A/C链接/B,/B/E链接/A,因为硬链接都是使用同一索引节点,而操作系统也是利用索引节点遍历,很难防范这种死循环;而软链接是不同的索引节点,同时索引节点是会记录这个文件是符号链接类型的,就能在合适的时候跳出循环
目录项状态
- 空闲状态:没有包含有效信息,未被VFS使用,只是slab分配了内存
- 未使用状态:还没被内核使用,引用计数器为0,已经和索引结点关联起来。包含有效信息,但必要时会被回收内存
- 正在使用状态:正在被内核使用,引用计数器为正数。包含有效信息,不会被丢弃
- 负状态:与目录项相关的索引结点被删除,但仍保存在目录项高速缓存,避免查找同名目录时遍历全部目录
目录项高速缓存
- 出现原因:如果VFS遍历路径名所有元素并把它们逐个解析成目录项对象,会浪费大量时间,因为是需要才创建的。因为程序的局部性,后面可能还需要用到这个目录项对象
- 实现:三个部分
- “被使用的”目录项双向链表:一个索引节点可以有多个目录项,这些目录项就用链表连起来,由索引节点中的i_dentry指向
- “最近被使用的”目录项双向链表:该链表含有未被使用和负状态的目录项对象。链头插新目录项,从链尾删除最久的目录项(LRU)
- 散列表,文件名对应目录项对象
文件对象file
描述进程怎么和一个打开的文件进行交互,由open创建,close撤销,在磁盘上没有对应的映像
- 一个文件被多个进程打开,就有多个file对象
- 主要信息是文件指针,即文件中的当前位置,下一个操作将在这个位置发生。因为多个进程可能同时访问一个文件,所以文件指针放在file而不是inode
和进程相关的数据结构
file_struct
所有与单个进程相关的信息(如打开的文件及文件描述符)都包含其中
- file对象在其中的静态数组fd_array,超过时可以建立新数组
fs_struct
包含文件系统和进程的信息
- 如根目录的目录项root,当前正在执行文件,当前目录的目录项pwd
路径名查找
- 如果路径名的第一个字符是"/",那么为绝对路径,从fs_sturct的root开始搜索
- 否则就是相对路径,从fs_struct的pwd开始搜索
- 过程:
- 检查和第一个名字匹配的目录项对象,没有就创建
- 获得对应的索引节点
- 从磁盘读出对应的文件,文件里是目录相关的信息(目录文件:inode+文件名)
- 从文件中找到和第二个名字匹配的目录项(不是目录项对象),创建目录项对象或在目录项高速缓存中找到,以此类推