开发者社区 > 博文 > 你不太了解的大咖——虚拟文件系统(VFS)
分享
  • 打开微信扫码分享

  • 点击前往QQ分享

  • 点击前往微博分享

  • 点击复制链接

你不太了解的大咖——虚拟文件系统(VFS)

  • 京东云技术交付部
  • 2021-01-08
  • IP归属:未知
  • 34520浏览

引言 

提到Linux的文件系统,大家肯定都比较清楚了解。它是系统中所有文件数据的集合。

文件系统不仅包含着文件中的数据而且还有文件系统的结构,所有Linux 用户和程序看到的文件、目录、软连接及文件保护信息等都存储在其中。

如果没有文件系统,那么将无法读取和写入系统中的所有文件,从而无法正常使用系统。因为Linux系统所有的服务程序都是通过一个个文件组成的,所以能够正常读写文件才能够保证正常使用系统。


VFS

好的,那么问题来了。。。

众所周知 Linux存在很多种类的文件系统格式,例如ext3,ext4,xfs。并且一块硬盘中如果存在多个分区,那么每一个分区都会有一个自己的文件系统。每个分区的文件系统,每种类型的文件系统格式,文件的组织和数据结构方式,读取和写入的方式都是不同的。如果方式不对,我们就不能读写该文件系统下的文件。

作为一个使用者,难道需要把所有文件系统的读写文件方式都记下来,才能正常使用?

答案是肯定不需要这样的,Linux作为一个当今最成熟稳定的系统之一,如果是这样设计的话肯定会被广大的使用者吐槽到崩溃。

那么总得有一个东西来代替用户记住这些东西啊,这个当然有,它就是虚拟文件系统VFS。

简单来讲,虚拟文件系统VFS就是充当一个中间人。它来负责和实际文件系统沟通和操作其中的文件。用户直接和VFS打交道。例如read,write,那么映射到VFS中就是sys_read,sys_write,那么VFS可以根据你操作的是哪个“实际文件系统”(哪个分区)来进行不同的实际的操作。


那么VFS为何如此神通广大呢,可以和任意不同的文件系统match上。原因是VFS中提供一个抽象的struct结构体,然后对于每一个具体的文件系统要把自己的字段和函数填充进去,这样就解决了异构问题。

接下来我们就来了解下VFS的四个主要的数据结构:

1.  超级块(super block)

2.  索引节点(inode)

3.  目录项(dentry)

4.  文件对象(file)



1、超级块(super block)

超级块,一个超级块对应一个文件系统(例如ext2类型的文件系统,此处是实际的文件系统,不是VFS)。

之前我们已经说了文件系统用于管理这些文件的数据格式和操作之类的,系统文件有系统文件自己的文件系统,同时对于不同的磁盘分区也有可以是不同的文件系统。那么一个超级块对于一个独立的文件系统。保存文件系统的类型、大小、状态等等。

(“文件系统”和“文件系统类型”不一样!一个文件系统类型下可以包括很多文件系统即很多的super_block)。

既然我们知道对于不同的文件系统有不同的super_block,那么对于不同的super_block的操作肯定也是不同的,所以我们在下面的super_block结构中可以看到上面说的抽象的struct结构。



2、索引节点

索引节点,保存的其实是实际的数据的一些信息,这些信息称为“元数据”(也就是对文件属性的描述)。

例如:文件大小,设备标识符,用户标识符,用户组标识符,文件模式,扩展属性,文件读取或修改的时间戳,链接数量,指向存储该内容的磁盘区块的指针,文件分类等等。

( 注意数据分成:元数据+数据本身 )

同时注意:inode有两种,一种是VFS的inode,一种是具体文件系统的inode。前者在内存中,后者在硬盘中。所以每次其实是将硬盘中的inode调进填充内存中的inode,这样才是算使用了硬盘文件的inode。

注意inode怎样生成的:每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定,一般每2KB就设置一个inode。一般文件系统中很少有文件小于2KB的,所以预定按照2KB分,一般inode是用不完的。所以inode在文件系统安装的时候会有一个默认数量,后期会根据实际的需要发生变化。

注意inode号:inode号是唯一的,表示不同的文件。其实在Linux内部的时候,访问文件都是通过inode号来进行的,所谓文件名仅仅是给用户容易使用的。当我们打开一个文件的时候,首先,系统找到这个文件名对应的inode号;然后,通过inode号,得到inode信息,最后,由inode找到文件数据所在的block,现在可以处理文件数据了。

inode和文件的关系:当创建一个文件的时候,就给文件分配了一个inode。一个inode只对应一个实际文件,一个文件也会只有一个inode。inodes最大数量就是文件的最大数量。



3、目录项

目录项,是描述文件的逻辑属性,只存在于内存中,并没有实际对应的磁盘上的描述,更确切的说是存在于内存的目录项缓存,为了提高查找性能而设计。


注意不管是文件夹还是最终的文件,都是属于目录项,所有的目录项在一起构成一颗庞大的目录树。例如:open一个文件/home/xxx/yyy.txt,那么/、home、xxx、yyy.txt都是一个目录项,VFS在查找的时候,根据一层一层的目录项找到对应的每个目录项的inode,那么沿着目录项进行操作就可以找到最终的文件。

注意:目录也是一种文件(所以也存在对应的inode)。打开目录,实际上就是打开目录文件。



4、文件对象

文件对象,注意文件对象描述的是进程已经打开的文件。因为一个文件可以被多个进程打开,所以一个文件可以存在多个文件对象。但是由于文件是唯一的,那么inode就是唯一的,目录项也是定的!

进程其实是通过文件描述符来操作文件的,注意每个文件都有一个32位的数字来表示下一个读写的字节位置,这个数字叫做文件位置。

一般情况下打开文件后,打开位置都是从0开始,除非一些特殊情况。Linux用file结构体来保存打开的文件的位置,所以file称为打开的文件描述。这个需要好好理解一下!file结构形成一个双链表,称为系统打开文件表。


对象间的联系

如上的数据结构并不是孤立存在的。正是通过它们的有机联系,VFS才能正常工作。如下的几张图是对它们之间的联系的描述。

如以下图所示,被Linux支持的文件系统,都有且仅有一个file_system_type结构而不管它有零个或多个实例被安装到系统中。每安装一个文件系统,就对应有一个超级块和安装点。超级块通过它的一个域s_type指向其对应的具体的文件系统类型。具体的 文件系统通过file_system_type中的一个域fs_supers链接具有同一种文件类型的超级块。同一种文件系统类型的超级块通过域s_instances链 接。


5、相互关系

超级块、安装点和具体的文件系统的关系


如下图,进程通过task_struct中的一个域files_struct files来了解它当前所打开的文件对象;而我们通常所说的文件 描述符其实是进程打开的文件对象数组的索引值。文件对象通过域f_dentry找到它对应的dentry对象,再由dentry对象的域d_inode找 到它对应的索引结点,这样就建立了文件对象与实际的物理文件的关联。

最后,还有一点很重要的是, 文件对象所对应的文件操作函数 列表是通过索引结点的域i_fop得到的。图中对第三部分源码的理解起到很大的作用。


进程与超级块、文件、索引结点、目录项的关系


到目前为止,文章主要都是从理论上来讲述VFS的运行机制,那么VFS到底能够解决什么问题呢。可以分为以下两大类。

1.  实现跨文件系统的文件操作

跨文件系统的文件操作的基本原理,举个例子,将vfat格式的磁盘上的一个文件a.txt拷贝到ext3格式的磁 盘上,命名为b.txt。这包含两个过程,对a.txt进行读操作,对b.txt进行写操作。读写操作前,需要先打开文件。

由前面的分析可知,打开文件 时,VFS会知道该文件对应的文件系统格式,以后操作该文件时,VFS会调用其对应的实际文件系统的操作方法。所以,VFS调用vfat的读文件方法将 a.txt的数据读入内存;在将a.txt在内存中的数据映射到b.txt对应的内存空间后,VFS调用ext3的写文件方法将b.txt写入磁盘;从而实现了最终的跨文件系统的复制操作。

2.  “一切皆是文件”的实现根本

不论是普通的文件,还是特殊的目录、设备等,VFS都将它们同等看待成文件,通过同一套文件操作界面来对它们进行操作。操作文件时需先打开;打开文件 时,VFS会知道该文件对应的文件系统格式;当VFS把控制权传给实际的文件系统时,实际的文件系统再做出具体区分,对不同的文件类型执行不同的操作。这也就是“一切皆是文件”的根本所在。


6、总结

VFS即虚拟文件系统是Linux文件系统中的一个抽象软件层;因为它的支持,众多不同的实际文件系统才能在Linux中的共存,跨文件系统操作才能实现。

VFS借助它四个主要的数据结构即超级块、索引节点、目录项和文件对象以及一些辅助的数据结构,向Linux中不管是普通的文件还是目录、设备、套接字等 都提供同样的操作界面,如打开、读写、关闭等。

只有当把控制权传给实际的文件系统时,实际的文件系统才会做出区分,对不同的文件类型执行不同的操作。由此 可见,正是有了VFS的存在,跨文件系统操作才能执行,Linux中的“一切皆是文件”的口号才能够得以实现。


感谢各位童鞋阅读,如果能够对大家有所帮助,欢迎点赞转发评论。

关注我们的公众号:云服务飞行团,更多精彩内容会持续放送!






共0条评论