虚拟文件系统
- 虚拟文件系统为用户空间程序提供了文件和文件系统的接口
- 通过VFS,程序可以通过标准的UNIX系统调用操作不同的文件系统和介质,包括各种软硬件设备
- Linux等现代操作系统引入VFS作为抽象层,极大方便系统调用
Unix文件系统
-
UNIX系统使用了四种和文件系统相关的抽象概念: 文件、目录项、索引结点和挂载点。
-
将文件的相关信息和文件加以区分
- 文件相关信息单独存储在索引结点中,又称为元数据,包括文件的控制权限、文件大小、属主和创建与访问时间等
- 文件相关信息和文件系统的相关信息密不可分,后者存储在***超级块(super block)***中,超级块是包含文件系统信息的数据结构。
- 文件按照索引结点存储在单独的块中,文件系统的控制信息存在超级块中
-
VFS中有四个主要对象类型
- 超级块对象,代表一个具体的已安装的文件系统
- 索引结点对象,代表一个具体文件
- inode才代表具体文件
- 目录项对象,代表一个目录项,是路径的组成部分
- 目录项不是目录,而是一个文件。不存在目录对象
- 文件对象,代表由进程打开的文件
- 每个进程都有自己的打开文件列表,文件对象是一个动态生成动态销毁的对象
-
超级块
- 超级块对象 super block
- 用于存储特定文件系统的信息
- 通常放在磁盘的特定扇区中,所以被称为超级块对象
- 并非基于磁盘的文件系统,内核会现场创建,并保存在内存中
- 超级块操作
- super_operations
- 超级块对象 super block
-
索引结点
- 索引结点对象 inode
- 索引结点对象包含了内核在操作文件或目录时的所有信息
- 索引结点对象都是在内存中创建的,不会写回硬盘的
- 索引结点操作
- inode_operations
- 索引结点对象 inode
-
目录项
- 目录项对象
- VFS把目录当做文件对待,解析目录时,将路径中的每个组成部分都是一个索引结点对象,比如"/bin/ls"中的‘/’、‘bin’和‘ls’。进行路径查找和解析是比较耗时的,为了方便操作,VFS引入了目录项dentry的概念,每个dentry都是路径的组成部分
- 目录项对象都是根据字符串形式现场创建的,并没有保存在磁盘
- 目录项状态
- 被使用
- 被使用的dentry对应一个有效的inode,即dentry结构体中d_inode指向的inode
- 该对象的引用计数d_count为正,至少有一个使用者,不能随意丢弃
- 未被使用
- 未被使用的dentry,其d_inode也指向一个inode,但是d_count为0
- 此时该dentry仍然在缓存中,可能会再次使用。不会立刻被释放,但如果系统要回收内存的话,可以被释放回收
- 负状态
- 负状态的dentry没有对应的有效inode,原因可能是inode已被删除,或者路径不再正确
- 此时将其缓存起来仍然有些用处,比如一个守护进程一直读一个不存在的文件,缓存dentry不至于让进程总是去搜索
- 被使用
- 目录项缓存
- 遍历路径名中所有元素并逐个解析成dentry,是非常费时费力的,所以内核引入目录项缓存dcache,将目录项对象都缓存起来
- 目录项缓存包括
- “被使用的"目录项链表
- 该链表通过inode中的i_dentry指针连接相关inode
- 一个给定的inode可能有多个链接(软硬链接),所有就有可能有多个目录项对象,因此用一个链表链接
- “最近使用的"双向链表
- 该链表包含所有 未被使用的 和 负状态的 dentry
- 总是在表头添加元素,所以回收dentry时从最后开始回收
- 哈希表和相应的哈希函数
- 快速将给定路径解析为相关目录项对象
- 哈希表由dentry_hashtable数组表示,每个元素都指向一个具有相同键值的目录项对象链表指针
- 哈希函数d_hash()
- 查找函数d_lookup()
- “被使用的"目录项链表
- 目录项操作
- dentry_operation
- 目录项对象
-
文件
- 文件对象
- 表示进程已经打开的文件。文件对象是已打开的文件(物理文件)在内存中的表示
- 多个进程可以打开同一个物理文件,所以一个物理文件会有多个文件对象
- 文件对象指向目录项对象,目录项对象指向索引结点inode
- 具体而言,是文件对象filep中的f_dentry指向目录项对象,目录项对象的d_inode指向索引结点inode
- 文件操作
- file_operations
- 文件对象
-
相关数据结构
- file_system_type
- 用于描述各种特定文件系统类型,用于支持不同文件系统
- struct file_system_type {}
- get_sb() 从磁盘读取超级块,并在文件系统安装时在内存中组装超级块对象
- 每个文件系统只有一个
- vfsmount
- 系统挂载时,将有一个vfsmount结构体在挂载点创建,代表文件系统的实例
- struct vfsmount {}
- 各种链表
- file_system_type
-
和进程相关的数据结构
-
每个进程都有自己的一组打开爱的文件,比如根文件系统、当前工作目录、挂载点等
-
struct files_struct {}
- 该结构提由进程描述符中的files指向,一般都是current->files
-
struct fs_struct {}
- 包含文件系统和进程相关的信息,由fs域指向,一般是current->fs
-
struct namespace {}
- 使得每个进程在系统中能看到唯一的安装文件系统,mm->namespace
-
每个进程都有指向自己的fs_struct和files_struct,多个进程可能指向同一个,比如通过带有CLONE_FILES和CLONE_FS标志创建的进程(其实是线程),所以这两个struct都有引用计数,以防出错
-
而对于namespace来说,除非使用CLONE_NEWS标志创建进程,会创建新的namespace结构体,否则所有进程共享一个namespace
-