VFS虚拟文件系统

虚拟文件系统

  • 虚拟文件系统为用户空间程序提供了文件和文件系统的接口
  • 通过VFS,程序可以通过标准的UNIX系统调用操作不同的文件系统和介质,包括各种软硬件设备
  • Linux等现代操作系统引入VFS作为抽象层,极大方便系统调用

Unix文件系统

  • UNIX系统使用了四种和文件系统相关的抽象概念: 文件、目录项、索引结点和挂载点。

  • 将文件的相关信息和文件加以区分

    • 文件相关信息单独存储在索引结点中,又称为元数据,包括文件的控制权限、文件大小、属主和创建与访问时间等
    • 文件相关信息文件系统的相关信息密不可分,后者存储在***超级块(super block)***中,超级块是包含文件系统信息的数据结构。
    • 文件按照索引结点存储在单独的块中,文件系统的控制信息存在超级块中
  • VFS中有四个主要对象类型

    • 超级块对象,代表一个具体的已安装的文件系统
    • 索引结点对象,代表一个具体文件
      • inode才代表具体文件
    • 目录项对象,代表一个目录项,是路径的组成部分
      • 目录项不是目录,而是一个文件。不存在目录对象
    • 文件对象,代表由进程打开的文件
      • 每个进程都有自己的打开文件列表,文件对象是一个动态生成动态销毁的对象
  • 超级块

    • 超级块对象 super block
      • 用于存储特定文件系统的信息
      • 通常放在磁盘的特定扇区中,所以被称为超级块对象
      • 并非基于磁盘的文件系统,内核会现场创建,并保存在内存中
    • 超级块操作
      • super_operations
  • 索引结点

    • 索引结点对象 inode
      • 索引结点对象包含了内核在操作文件或目录时的所有信息
      • 索引结点对象都是在内存中创建的,不会写回硬盘的
    • 索引结点操作
      • inode_operations
  • 目录项

    • 目录项对象
      • 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 {}
        • 各种链表
  • 和进程相关的数据结构

    • 每个进程都有自己的一组打开爱的文件,比如根文件系统、当前工作目录、挂载点等

    • 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

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy