图解Linux虚拟文件系统(VFS)之关系篇

云计算 虚拟化
VFS的设计目标是将不同类型的文件系统抽象为一个统一的接口,使得用户和应用程序无需关心底层文件系统的具体实现细节。通过VFS用户可以使用相同的系统调用(如open、read、write等)来访问不同类型的文件系统,包括本地文件系统(如ext4、XFS等)、网络文件系统(如NFS、CIFS等)以及虚拟文件系统(如procfs、sysfs等)。

大家好,今天和大家探讨一下Linux虚拟文件系统,虚拟文件系统是我一直想要去聊的一个知识点,如果你想从事Linux开发相关的工作,一定要了解虚拟文件系统。

1.什么是虚拟文件系统?

Linux虚拟文件系统(Virtual File System,VFS)是Linux操作系统中的一个重要组成部分,它提供了一个统一的接口,使得用户和应用程序可以通过相同的方式访问不同类型的文件系统。

图片图片

VFS的设计目标是将不同类型的文件系统抽象为一个统一的接口,使得用户和应用程序无需关心底层文件系统的具体实现细节。通过VFS用户可以使用相同的系统调用(如open、read、write等)来访问不同类型的文件系统,包括本地文件系统(如ext4、XFS等)、网络文件系统(如NFS、CIFS等)以及虚拟文件系统(如procfs、sysfs等)。

VFS由以下几个主要组件组成:

  • 虚拟文件系统接口:VFS定义了一组通用的文件系统操作接口。
  • 超级块(super_block):每个文件系统都有一个超级块,它包含了文件系统的元数据信息,如文件系统类型、块大小、inode表等,超级块提供了对文件系统的整体描述和管理。
  • 目录项(dentry):dentry是目录项的缩写,用于表示文件系统中的目录和文件,dentry包含了目录和文件对应的inode指针,通过它可以快速定位到目录下的文件或子目录。
  • 文件节点(inode):inode是文件系统中的一个数据结构,用于存储文件或目录的元数据信息,如文件大小、权限、所有者等,每个文件或目录都对应一个唯一的inode。
  • 文件对象(file):file是表示打开文件的数据结构,它包含了对应的inode指针、当前读写位置等信息,通过file可以进行文件的读写操作。

2.Linux系统文件树

对于一个普通的Linux用户或者运维人员,Linux系统文件树通常的样子如下图,以根文件系统根目录为起点,通过根目录遍历整个文件树。

图片图片

而在系统开发人员眼中,Linux系统文件树则变成这样一个结构,每个文件和目录都对应一个dentry结构体。

图片图片

dentry到底是什么?

dentry结构体的主要作用是提供文件系统层次结构的表示,它们通过形成一个树状结构来组织目录和文件,每个dentry都有一个唯一的路径名,可以通过遍历dentry树来找到特定文件或目录。

struct dentry结构体定义:

struct dentry {
    struct dentry *d_parent;
    struct qstr d_name;
    struct inode *d_inode;
   
    const struct dentry_operations *d_op;
    struct super_block *d_sb; 
    struct list_head d_child;
    struct list_head d_subdirs;
    ....
};

struct dentry结构体通过d_parent,d_child,d_subdirs等成员将文件系统组成一颗文件树,要了解Linux文件系统,我们得学会运用dentry。

小节:dentry是VFS重要的组成部分,要理解VFS先从dentry开始。

3.文件系统注册

通过前面的学习,我们了解到dentry结构的重要性,接下来围绕dentry结构体来解析文件VFS各组件之间的关系,我们先来看一下整体架构图:

图片图片

Linux文件系统对应一个file_system_type结构体对象,file_system_type结构体定义如下:

struct file_system_type {
    const char *name;
    int fs_flags;
    int (*init_fs_context)(struct fs_context *);
    const struct fs_parameter_spec *parameters;
    struct dentry *(*mount) (struct file_system_type *, int,
                 const char *, void *);
    void (*kill_sb) (struct super_block *);
    ......
};

ramfs文件系统定义如下,name表示文件系统类型,当ramfs文件系统需要实例化,需要通过name查找全局文件系统链表头找到对应的已注册文件系统,再通过已注册文件系统创建超级块(super block)。

static struct file_system_type ramfs_fs_type = {
      .name = "ramfs",
      .init_fs_context = ramfs_init_fs_context,
      .parameters = ramfs_fs_parameters,
      .kill_sb = ramfs_kill_sb,
      .fs_flags = FS_USERNS_MOUNT,
};

定义好文件系统后,通过register_filesystem函数将文件系统注册至Linux系统,注册成功的文件系统会插入全局文件系统链表,已注册的文件系统能够用来创建超级块(super block)。

通过cat /proc/filesystems查看系统所有已注册文件系统

图片图片

4.文件系统挂载

文件系统挂载就是新文件系统生成一个挂载实例(struct mount),让新挂载实例和父文件系统的挂载实例建立父子关系。

一个新的挂载实例包括几个重要部分:

  • 超级块(super_block)

超级块用来指示新的文件系统对应的设备。

  • 父挂载实例(mount)

父挂载实例表示挂载点所处的文件系统挂载实例。

  • 挂载点(mountpoint)

挂载点是新文件系统和父文件系统之间连接的纽带。

  • 文件系统根目录(dentry)

每个文件系统都有一个根目录,当索引一个文件路径进入到一个新的文件系统后,会从新的文件系统根目录开始索引。

4.1 索引挂载点

索引挂载点的目的是为了获取挂载点的struct path记录信息,挂载点索引的过程就是struct path记录信息不断被替换的过程。

图片图片

以挂载点/mnt/test/dir为例来讲解:

  1. 索引/目录,获取/目录的path记录信息。
  2. 索引mnt目录,获取mnt目录的path记录信息,并覆盖/目录的path记录信息。
  3. 索引test目录,获取test目录的path记录信息,并覆盖mnt目录的path记录信息。
  4. 索引dir目录,获取dir目录的path记录信息,并覆盖test目录的path记录信息。
  5. 最终获取到挂载点dir的struct path记录信息。

struct path结构体定义如下:

struct path {
      struct vfsmount *mnt;
      struct dentry *dentry;
};

mnt:记录挂载点所在文件系统的挂载实例。

dentry:挂载点目录dentry。

4.2 创建新文件系统挂载实例

  • 创建超级块

要创建超级块首先要知道文件系统类型,mount命令通过-t参数指定文件系统类型,通过mount命令传入的文件系统类型,可以遍历全局文件系统链表找到已注册的文件系统,通过已注册的文件系统创建超级块。

  • 创建新文件系统挂载实例

创建超级块后,通过超级块的信息创建新文件系统挂载实例。

  • 创建挂载点

通过挂载点dentry创建一个挂载点。

4.3 新旧挂载实例对接

通过前面的过程,我们已经具备文件系统挂载三要素:

  • 新文件系统挂载实例。
  • 父文件系统挂载实例。
  • 挂载点。

通过挂载三要素,我们就能完成新旧挂载实例对接,完成对接后,新文件系统挂载实例的mnt_parent指向父挂载实例,整个挂载过程就已经完成。

新文件系统挂载成功后,Linux系统文件树将新文件系统嫁接进来,如下图:

图片图片


此时我们想要操作新文件系统中的文件,只需要根据路径名层层索引获取文件path信息,path信息记录dentry信息,dentry绑定了inode对象。

最终获取到inode文件节点就能操作文件了。

责任编辑:武晓燕 来源: 物联网心球
相关推荐

2020-07-22 14:53:06

Linux系统虚拟文件

2019-09-20 10:04:45

Linux系统虚拟文件

2018-08-24 10:10:25

Linux文件系统技术

2022-01-14 08:39:47

鸿蒙HarmonyOS应用

2019-05-29 16:33:32

Linux虚拟系统

2019-05-22 09:00:16

Linux虚拟文件系统

2023-12-06 09:32:35

Linux系统

2009-07-21 10:49:26

ASP.NET虚拟文件

2020-10-12 17:40:44

lsofLinux虚拟文件

2022-04-21 14:09:17

lsofLinux虚拟文件

2021-04-12 05:44:44

Linux文件系统

2021-01-28 11:37:51

虚拟文件

2010-03-02 14:21:30

Linux操作系统

2019-06-14 14:58:58

虚拟文件系统Linux

2021-08-24 10:57:24

Linux文件系统内存

2017-02-06 16:18:57

微软GitGVFS

2010-01-21 09:15:05

Linux嵌入式文件系

2021-05-31 07:50:59

Linux文件系统

2023-09-27 23:19:04

Linuxmount

2011-01-13 14:10:30

Linux文件系统
点赞
收藏

51CTO技术栈公众号