精华内容
下载资源
问答
  • VFS

    千次阅读 2019-10-25 08:47:25
    VFS是Linux非常核心的一个概念,linux下的大部分操作都要用到VFS的相关功能。这里从使用者的角度,对VFS进行了简单说明。使用者不但需要知道Linux下有哪些文件操作的函数,还需要对VFS的结构有一个比较清晰的了解,...

    2、VFS的构建

    所谓VFS的构建就是加载实际文件系统的过程,也就是mount被调用的过程。如下图所示,以mount一个ext2的文件系统为例。
    这是一个经过简化的Ext2磁盘结构,只是用于说明用它构建VFS的基本过程。
    mount命令的一般形式为:mount /dev/sdb1 /mnt/mysdb1
    /dev/sdb1是设备名,/mnt/mysdb1是挂载点。
    VFS文件系统的基本结构是dentry结构体与inode结构体。
    Dentry代表一个文件目录中的一个点,可以是目录也可以是文件。
    Inode代表一个在磁盘上的文件,它与磁盘文件一一对应。
    Inode与dentry不一定一一对应,一个inode可能会对应多个dentry项。(hard link)Mount时,linux首先找到磁盘分区的super block,然后通过解析磁盘的inode table与file data,构建出自己的dentry列表与indoe列表。
    需要注意的是,VFS实际上是按照Ext的方式进行构建的,所以两者非常相似(毕竟Ext是Linux的原生文件系统)。
    比如inode节点,Ext与VFS中都把文件管理结构称为inode,但实际上它们是不一样的。Ext的inode节点在磁盘上;VFS的inode节点在内存里。Ext-inode中的一些成员变量其实是没有用的,如引用计数等。保留它们的目的是为了与vfs-node保持一致。这样在用ext-inode节点构造vfs-inode节点时,就不需要一个一个赋值,只需一次内存拷贝即可。
    如果是非EXT格式的磁盘,就没有这么幸运了,所以mount非EXT磁盘会慢一些。

    4 VFS的结构

    构建出VFS文件系统后,下一步是把第一节中提到的目录模型映射到VFS结构体系中。
    上文提到了VFS主要由denty与inode构成。Dentry用于维护VFS的目录结构,每个dentry项就代表着我们用ls时看的的一项(每个目录和每个文件都对应着一个dentry项)。Inode为文件节点,它与文件一一对应。Linux中,目录也是一种文件,所以dentry也会对应一个inode节点。

    5 Dentry cache

    每个文件都要对应一个inode节点与至少一个dentry项。假设我们有一个100G的硬盘,上面写满了空文件,那个需要多少内存才能重建VFS呢?
    文件最少要占用1个block(一般是4K)。假一个dentry与一个inode需要100byte,则dentry与inode需要占用1/40的空间。1G硬盘则需要2.5M空间。最近都开始换装1T硬盘了,需要 25G的内存才能放下inode与dentry,相信没有几台电脑可以承受。
    为了避免资源浪费,VFS采用了dentry cache的设计。
    当有用户用ls命令查看某一个目录或用open命令打开一个文件时,VFS会为这里用的每个目录项与文件建立dentry项与inode,即“按需创建”。然后维护一个LRU(Least Recently Used)列表,当Linux认为VFS占用太多资源时,VFS会释放掉长时间没有被使用的dentry项与inode项。
    需要注意的是:这里的建立于释放是从内存占用的角度看。从Linux角度看,dentry与inode是VFS中固有的东西。所不同的只是VFS是否把dentry与inode读到了内存中。对于Ext2/3文件系统,构建dentry与inode的过程非常简单,但对于其他文件系统,则会慢得多。
    了解了Dentry cache的概念,才能明白为何下面会有两种定位文件的方式。

    6 无denty时定位文件

    因为上面提到的Denty Cache,VFS并不能保证随时都有dentry项与inode项可用。下面是无dentry项与inode项时的定位方式。
    为了简化问题,这里假设已经找到了dir的dentry项(找到dentry的过程会在后面讲解)。
    首先,通过dir对应的dentry0找到inode0节点,有了inode节点就可以读取目录中的信息。其中包含了该目录包含的下一级目录与文件文件列表,包括name与inode号。实际上用ls命令查看的就是这些信息。“ls -i”会显示出文件的inode号。

    ls -i
    975248 subdir0 975247 subdir1 975251 file0

    接着,根据file1对应的inode号重建inode4,并通过文件数据与inode4重建file1的dentry节点。然后,根据通过根据subdir0对应的inode号重建inode2,并通过文件数据(目录也是文件)与inode2重建subdir0的dentry节点:dentry1。

    ls -i

    975311 file1 975312 file2

    最后,就可以通过inode4节点访问文件了。
    注意:文件对应的inode号是确定的,只是inode结构体需要重新构造。

    7 有dentry时定位文件

    一旦在Dentry cache中建立了dentry项,下次访问就很方便了。
    Dentry中的一个关键变量是d_subdirs,它保存了下一级目录的列表,用于快速定位文件。
    首先,在代表dir目录的dentry0的d_subdirs中查找名字为“subdir0”的dentry项,找到了dentry1。
    然后在dentry1中查找名字为“file1”的dentry项,然后找到了file1对应的dentry项,
    最后通过file1对应的dentry项获得file1对应的inode4。
    与无dentry项时比较,有dentry项时的操作精简了许多。

    10 进程对文件的管理

    进程控制块task_struct中有两个变量与文件有关:fsfiles

    files中存储着rootpwd两个指向dentry项的指针。用户定路径时,绝对路径会通过root进行定位;相对路径会的通过pwd进行定位。(一个进程的root不一定是文件系统的根目录。比如ftp进程的根目录不是文件系统的根目录,这样才能保证用户只能访问ftp目录下的内容)

    fs是一个file object列表,其中每一个节点对应着一个被打开了的文件。当进程定位到文件时,会构造一个file object,并通过f_inode 关联到inode节点。文件关闭时(close),进程会释放对应对应file objectFile object中的f_mode是打开时选择的权限,f_pos为读写位置。当打开同一个文件多次时,每次都会构造一个新的file object。每个file object中有独立的f_modef_pos

    展开全文
  • VFS-Java:VFS Java-源码

    2021-07-13 11:07:34
    VFS-Java 虚拟文件系统应用程序。 它是出于教育目的而编写的,目的是展示如何实施此测试任务。
  • Apache Commons VFS项目 Apache Commons VFS是一个虚拟文件系统库。 文献资料 可以在上找到更多信息。 可以浏览 。 与Apache Commons VFS Project的用法有关的问题应张贴到。 在哪里可以获得最新版本? 您可以从...
  • vfs_fonts大全

    2021-09-08 13:34:38
    vfs_fonts大全
  • Apache Commons VFS实用程序,例如到Apache Mina FTP服务器的桥接器,到Apache Mina SSHD / SCP / SFTP服务器的桥接器以及可脚本化的Java Shell /控制台,可提供带有VFS文件系统命令和操作的命令行界面。
  • VFS Shell互操作 该模块是VFS的扩展,它允许Shell脚本与VFS代理进行通信。
  • VFS本地 VFS是用于系统的抽象接口。 此模块是参考实现,并使用节点api提供到本地系统的vfs接口。 这也经常与vfs-socket结合使用,以通过任何类型的网络套接字为远程系统提供vfs接口。 设置(fsOptions)-> vfs 这...
  • var vfs = require ( 'vfs-local' ) ( { root : process . cwd ( ) , httpRoot : root , } ) ; require ( 'http' ) . createServer ( require ( 'stack' ) ( require ( 'vfs-http-adapter' ) ( "/rest/" , vfs ) ...
  • VFS-资源-适配器 VFS 入站资源适配器 该项目是在入站资源适配器中使用 commons vfs2 文件监视器的示例。 所有这些都在 TomEE web 项目中可用 信息 在 Web 模块中的 MDB 中配置 sftp 详细信息 构建父 pom mvn tomee...
  • minix vfs分析

    2015-09-11 10:05:36
    linux是从minix发展而来,可以通过了解minix vfs学习和linux vfs的不同之处
  • 适用于Apache Commons VFS的Dropbox插件
  • 什么是vfs以及vfs的作用

    万次阅读 2017-06-22 16:34:49
    vfs(虚拟文件系统)是什么?我们知道文件系统的种类有很多。除了Linux标准的文件系统Ext2/Ext3/Ext4外,还有很多种文件系统 。linux通过叫做VFS的中间层对这些文件系统提供了完美的支持。在大部分情况下,用户通过...

    vfs(虚拟文件系统)是什么?

    我们知道文件系统的种类有很多。除了Linux标准的文件系统Ext2/Ext3/Ext4外,还有很多种文件系统 。linux通过叫做VFS的中间层对这些文件系统提供了完美的支持。在大部分情况下,用户通过libc和kernel的VFS交互,不需要关心底层文件系统的具体实现。

    我的理解,vfs就是对各种文件系统的一个抽象,它为各种文件系统提供了一个通用的接口,类似于c++中虚基类的作用,而每一种具体的文件系统则将其物理组织结构转换为虚拟文件系统的通用模型。

    vfs的作用

    vfs所隐含的思想是把表示很多不同种类文件系统的共同信息放入内核;其中有一个字段或函数来支持Linux所支持的所有实际文件系统所提供的任何操作。对所调用的每个读、写或其他函数,内核都能把它们替换成支持本地Linux文件系统、NTFS文件系统,或者文件所在的任何其他文件系统的实际函数。

    有了vfs,就能很容易实现不同文件系统之间的数据读写,因为它们对外接口都是一样的,都是vfs导出的通用接口。
    以下ulk3书上的例子:
    例如,假设一个用户输入以下shell命令:
    $ cp /floppy/TEST /tmp/test

    其中/floppy是MS-DOS磁盘的一个安装点,而/tmp是一个标准的第二扩展文件系统(second Extended Filesystom, Ext2)的目录。正如图(a)所示,VFS是用户的应用程序与文件系统实现之间的抽象层。因此,cp程序并不需要知道/floppy/TEST 和 /tmp/test是什么文件系统类型。相反,cp程序直接与VFS交互,这是通过Unix程序设计人员都熟悉的普通系统调用来进行的。cp的执行代码如图(b)所示:
    这里写图片描述

    vfs支持的文件系统的类型

    1. 磁盘文件系统 这类文件系统数目最多,最常见:ext2/ext3/ext4文件系统(关注重点)
    2. 特殊文件系统。如/proc文件系统
    3. 网络文件系统,如NFS

    VFS存在的意义

    • 向上,对应用层提供一个标准的文件操作接口;
    • 对下,对文件系统提供一个标准的接口,以便其他操作系统的文件系统可以方便的移植到Linux上;

    通用文件模型

    前面提过vfs所隐含的思想是把表示很多不同种类文件系统的共同信息放入内核,vfs通过引入一个通用文件模型来表示所有支持的文件系统。要实现每个具体的文件系统,必须将其物理组织结构转换为虚拟文件系统的通用文件模型。

    通用文件模型由下列对象类型组成:

    • 超级块对象(superblock object):存放已安装文件系统的有关信息。对基于磁盘的文件系统,这类对象通常对应于存放在磁盘上的文件系统控制块(filesystem control block)。
    • 索引节点对象(inode object):存放关于具体文件的一般信息。对基于磁盘的文件系统,这类对象通常对应于在磁盘上的文件控制块(file control block)。每个索引节点对象都有一个索引节点号,这个节点号唯一地标识文件系统中的文件。
      inode由两个主要部分组成:
      1. 描述文件状态的元数据,文件元数据包括文件大小,权限,类型,时间;
      2. 文件数据描述,则用来定义文件数据在磁盘上的存放位置。
    • 文件对象(file object):存放打开文件与进程之间进行交互的有关信息。这类信息仅当进程访问文件期间在于内核内存中
    • 目录项对象(dentry object):存放目录项(也就是文件的特定名称)与对应文件进行链接的有关信息。每个磁盘文件系统都以自己特有的方式将该类信息存在磁盘上。底层文件系统的许多操作严重依赖文件的inode,在进行文件操作前,我们需要根据路径名找到文件对应的inode。我们知道文件系统是树状结构的,因此需要从根目录通过目录树找到要操作的文件或目录,这个遍历过程涉及到磁盘操作,非常耗时。根据局部性原理,很有必要把这个查找过程cache起来,dentry就是为了加快目录遍历操作引入的数据结构。

    (第一次看到这些概念,可能你也很懵逼,很正常,后面看了具体的数据结构代码可能会好点)
    下图所示是一个简单的示例,说明进程怎样与文件进行交互。
    这里写图片描述
    三个不同进程已经打开同一个文件,其中两个进程使用同一个硬链接(我觉得是打开同一路径名文件)。在这种情况下,其中的每个进程都使用自己的文件对象,但只需要两个目录项对象,每个硬链接对应一个目录项对象。这两个目录项对象指向同一个索引节点对象,该索引节点对象标识超级块对象,以及随后的普通磁盘文件。

    链接

    软链接

    软链接又称为符号链接,软链接文件内容指向一个文件路径,也就是文件真实位置,软链接指向的文件也可以是软链接。

    硬链接

    硬链接是两个文件共享同一个inode。

    注意的地方

    在处理文件时,应用空间和内核空间使用的对象是不同的。对应用程序来说,文件描述符用来表示一个文件,这个文件描述符是打开文件时内核分配给这个文件的一个整数,注意,这个文件描述符只在本进程内有效;而对于内核来说,则使用一个inode来表示一个文件,这个inode可能对应着应用层多个进程内的多个文件描述符。
    文件在内核内存中是由一个file数据结构来表示的。这种数据结构中包含一个称为f_op的字段,该字段中包含一个指向所访问文件的函数指针,当然还包括读文件的函数。sys_read()查找到指向该函数的指针,并调用它。这样一来,应用程序的read()就被转化为相对间接的调用:file->f_op->read(…);
    与之类似,write()操作也会引发一个与输出文件相关的Ext2写函数的执行。简而言之,内核负责把一组合适的指针分配给与每个打开文件相关的file变量,然后负责调用针对每个具体文件系统的函数(由f_op字段指向)。

    展开全文
  • VFS文件编辑

    2013-05-13 15:15:49
    VFS文件编辑
  • vfs5 本固件是VOX vfs5脚踏开关的软件实现,兼容VT/VT+系列吉他功放。 它在 VT20+ 上进行了测试。 查看 ,了解从原始 VOX 脚踏开关反向设计的模拟电路。 我们在 arduino 的数字引脚 5 上生成一个 PWM,将端口设置...
  • vfs495:适用于Linux的Validity VFS495(138a:003f)驱动程序和实用程序
  • Linux之VFS

    2021-08-23 10:03:39
    一、概述 ...虚拟文件系统(Virtual File System,简称VFS)是Linux内核的子系统之一,它为用户程序提供文件和文件系统操作的统一接口,屏蔽不同文件系统的差异和操作细节。借助VFS可以直接使用ope

    一、概述

    ext系列文件系统和xfs文件系统是Linux使用最多的文件系统,也是很多发布版本默认选择的文件系统。而事实上,Linux支持的文件系统非常广泛,Minix,FAT,VFAT,NFS,NTFS…等等。我们知道一个分区代表了一个文件系统,不同的分区可以安装不同的文件系统。由此可知,Linux支持多种不同文件系统,要实现这个目的,就要将对各种不同文件系统和管理纳入到一个统一的框架中,让内核中的文件系统界面成为一条文件系统“总线”,使用户程序 可以通过同一个文件系统操作界面,也就是同一组系统调用,对各种不同的文件系统(以及 文件)进行操作。那么在Linux系统中,如何管理和调用这些文件系统的接口呢?通过VFS来实现。

    Linux之VFS

    1.1 VFS定义和作用

    我们知道在Linux系统中一切皆文件,在Linux系统中基本上把其中的所有内容都看作为文件,除了我们普遍意义上理解的文件之外,像目录、字符设备、块设备、 套接字、进程、线程、管道等都被视为“文件”。例如对于块设备,我们通过fdisk -l显示块设备列表,其实块设备可以理解为在文件夹/dev下面的文件,只不过这些文件是特殊的文件。"一切皆文件"是Linux的基本哲学之一,实现这一行为的基础,正是Linux的虚拟文件系统机制。

    VFS是一个抽象层,其向上提供了统一的文件访问接口,而向下则兼容了各种不不同类型的文件系统。不仅仅是诸如Ext2、ExtExt4、XFS、windows家族的NTFS和Btrfs等常规意义上的文件系统,还可以是比如上图的proc等伪文件系统和设备也可以是诸如NFS、CIFS等网络文件系统

    VFS,Virtual File System虚拟文件系统,也称为虚拟文件系统开关(Virtual Filesystem Switch),就是采用标准的Linux系统调用读写位于不同物理介质上的不同文件系统,即为各类文件系统提供了一个统一的操作界面和应用编程接口,VFS是一个内核软件层

    VFS是一个可以让open()、read()、write()等系统调用不用关心底层的存储介质和文件系统类型就可以工作的抽象层,如下图所示。

     

    举个例子,Linux用户程序可以通过read() 来读取ext3NFSXFS等文件系统的文件,也可以读取存储在SSDHDD等不同存储介质的文件,无须考虑不同文件系统或者不同存储介质的差异。

    另外,VFS实现了一部分公共的功能,例如页缓存和inode缓存等,从而避免多个文件系统重复实现的问题。有关高速缓存,后续章节还有介绍。 

    1.2 VFS原理

    VFS之所以能够衔接各种各样的文件系统,是因为它抽象了一个通用的文件系统模型,定义了通用文件系统都支持的、概念上的接口。新的文件系统只要支持并实现这些接口,并注册到Linux内核中,即可安装和使用。

    举个例子,比如Linux写一个文件:

    int ret = write(fd, buf, len);

    调用了write()系统调用,它的过程简要如下:

    • 首先,勾起VFS通用系统调用sys_write()处理。
    • 接着,sys_write()根据fd找到所在的文件系统提供的写操作函数,比如op_write()
    • 最后,调用op_write()实际的把数据写入到文件中。

    操作示意图如下:

    二、文件系统分类

    2.1 基于磁盘的文件系统

    管理本地磁盘和模拟磁盘的设备
    Linux的Ext2、Ext3和ReiserFS 
    Unix文件系统的变种,如sysv、UFS、MINIX和VERITAS VxFS。 
    微软的文件系统,如MS-DOS、VFAT、NTFS 
    ISO9660 CD-ROM文件系统和UDF(Universal Disk Format)DVD文 件系统 
    其他文件系统如IBM OS/2中的HPFS、Apple’s Macintosh的HFS、AFFS 和ADFS等。

    2.2 网络文件系统

    它允许方便访问网络上其他计算机的文件系统。VFS支持的网络文件系统有 NFS、Coda、AFS(Andrew filesystem)、CIFS(Common Internet Filesystem) 和NCP(Novell’s NetWare Core Protocol)。

    2.3 特殊文件系统

    它不管理磁盘空间,/proc就是一个特殊的文件系统。

    三、VFS内部结构和对象类型 

    VFS层通过定义一个清晰的VFS接口,以将文件系统的通用操作和具体实现分开。多个VFS接口的实现可以共存在同一台机器上,它允许访问已装在本地的多个类型的文件系统。

    VFS提供了在网络上唯一标识一个文件的机制。VFS基于称为vnode文件表示结构,该结构包括一个数值标识符以表示位于整个网络范围内的唯一文件。该网络范围的唯一性用来支持网络文件系统。内核中为每个活动节点(文件或目录)保存一个vnode结构。

    VFS根据文件系统类型调用特定文件类型操作以处理本地请求,通过调用NFS协议程序来处理远程请求。文件句柄可以从相应的vnode中构造,并作为参数传递给程序。它的下一层实现文件系统类型或远程文件系统协议。

    Linux为了实现这种VFS系统,采用面向对象的设计思路,主要抽象了四种对象类型:
        超级块对象(superblock object)表示整个文件系统

        索引节点对象(inode object)表示一个单独的文件

        目录项对象(dentry object)表示一个单独的目录项(或者称作目录条目)

        文件对象(file object)表示一个打开的文件

    如下图所示:

    æµè°Linuxèææ件系ç»

    每个对象都包含一组操作方法,用于操作相应的文件系统。 

    备注:Linux将目录当做文件对象来处理,是另一种形式的文件,它里面包含了一个或多个目录项。而目录项是单独抽象的对象,主要包括文件名和索引节点号。因为目录是可以层层嵌套,以形成文件路径,而路径中的每一部分,其实就是目录项。

    接下来介绍一下各个对象的作用以及相关操作。

    3.1 超级块

    超级块用于存储文件系统的元信息,由super_block结构体表示,定义在<linux/fs.h>中,元信息里面包含文件系统的基本属性信息,比如有:

    • 索引节点信息
    • 挂载的标志
    • 操作方法 s_op
    • 安装权限
    • 文件系统类型、大小、区块数
    • 等等等等

    其中操作方法 s_op 对每个文件系统来说,是非常重要的,它指向该超级块的操作函数表,包含一系列操作方法的实现,这些方法有:

    • 分配inode
    • 销毁inode
    • 读、写inode
    • 文件同步
    • 等等

    当VFS需要对超级块进行操作时,首先要在超级块的操作方法 s_op 中,找到对应的操作方法后再执行。比如文件系统要写自己的超级块:

    superblock->s_op->write_supper(sb);

    创建文件系统时,其实就是往存储介质的特定位置,写入超级块信息;而卸载文件系统时,由VFS调用释放超级块。

    Linux支持众多不同的文件系统,file_system_type结构体用于描述每种文件系统的功能和行为,包括:

    • 名称、类型等
    • 超级块对象链表

    当向内核注册新的文件系统时,其实是将file_system_type对象实例化,然后加入到Linux的根文件系统的目录树结构上。

    3.2 索引

    索引节点对象包含Linux内核在操作文件、目录时,所需要的全部信息,这些信息由inode结构体来描述,定义在<linux/fs.h>中,主要包含:

    • 超级块相关信息
    • 目录相关信息
    • 文件大小、访问时间、权限相关信息
    • 引用计数
    • 等等

    一个索引节点inode代表文件系统中的一个文件,只有当文件被访问时,才在内存中创建索引节点。与超级块类似的是,索引节点对象也提供了许多操作接口,供VFS系统使用,这些接口包括:

    • create(): 创建新的索引节点(创建新的文件)
    • link(): 创建硬链接
    • symlink(): 创建符号链接。
    • mkdir(): 创建新的目录。

    等等,我们常规的文件操作,都能在索引节点中找到相应的操作接口。

    3.3 目录项

    前面提到VFS把目录当做文件对待,比如/usr/bin/vimusrbinvim都是文件,不过vim是一个普通文件,usrbin都是目录文件,都是由索引节点对象标识。

    由于VFS会经常的执行目录相关的操作,比如切换到某个目录、路径名的查找等等,为了提高这个过程的效率,VFS引入了目录项的概念。一个路径的组成部分,不管是目录还是普通文件,都是一个目录项对象。/usrbinvim都对应一个目录项对象。不过目录项对象没有对应的磁盘数据结构,是VFS在遍历路径的过程中,将它们逐个解析成目录项对象。

    目录项由dentry结构体标识,定义在<linux/dcache.h>中,主要包含:

    • 父目录项对象地址
    • 子目录项链表
    • 目录关联的索引节点对象
    • 目录项操作指针
    • 等等

    目录项有三种状态:

    • 被使用:该目录项指向一个有效的索引节点,并有一个或多个使用者,不能被丢弃。
    • 未被使用:也对应一个有效的索引节点,但VFS还未使用,被保留在缓存中。如果要回收内存的话,可以撤销未使用的目录项。
    • 负状态:没有对应有效的索引节点,因为索引节点被删除了,或者路径不正确,但是目录项仍被保留了。

    将整个文件系统的目录结构解析成目录项,是一件费力的工作,为了节省VFS操作目录项的成本,内核会将目录项缓存起来。

    3.4 文件

    文件对象是进程打开的文件在内存中的实例。Linux用户程序可以通过open()系统调用来打开一个文件,通过close()系统调用来关闭一个文件。由于多个进程可以同时打开和操作同一个文件,所以同一个文件,在内存中也存在多个对应的文件对象,但对应的索引节点和目录项是唯一的。

    文件对象由file结构体表示,定义在<linux/fs.h>中,主要包含:

    • 文件操作方法
    • 文件对象的引用计数
    • 文件指针的偏移
    • 打开文件时的读写标识
    • 等等等等

    类似于目录项,文件对象也没有实际的磁盘数据,只有当进程打开文件时,才会在内存中产生一个文件对象。

    每个进程都有自己打开的一组文件,由file_struct结构体标识,该结构体由进程描述符中的files字段指向。主要包括:

    • fdt
    • fd_array[NR_OPEN_DEFAULT]
    • 引用计数

    fd_array数组指针指向已打开的文件对象,如果打开的文件对象个数 > NR_OPEN_DEFAULT,内核会分配一个新数组,并将 fdt 指向该数组。

    除此之外,内核还为所有打开文件维持一张文件表,包括:

    • 文件状态标志
    • 文件偏移量

    关于多进程打开同一文件以及文件共享更详细的信息,可以阅读《UNIX环境高级编程》第三章。

    四、从VFS到具体文件系统

    4.1 挂载

    我们从上面得知,VFS可以管理各种文件系统,那么VFS和文件系统怎么关联的呢?给用户如何展示的呢?通过挂载。

    如下图所示,该系统根文件系统是Ext3文件系统,而在其/mnt目录下面又分别挂载了Ext4文件系统和XFS文件系统。最后形成了一个由多个文件系统组成的文件系统树。

    挂载是用户态发起的命令,就是我们知道的mount命令,该命令执行的时候需要指定文件系统的类型(本文假设Ext2)和文件系统数据的位置(也就是设备)。通过这些关键信息,VFS就可以完成Ext2文件系统的初始化,并将其关联到当前已经存在的文件系统中,也就是建立其图2所示的文件系统树

    在挂载的过程中,最为重要的数据结构是vfsmount,它代表一个挂载点。其次是dentry和inode,这两个都是对文件的表示,且都会缓存在哈希表中以提高查找的效率。

    其中inode是对磁盘上文件的唯一表示,其中包含文件的元数据(管理数据)和文件数据等内容,但不含文件名称。而dentry则是为了Linux内核中查找文件方便虚拟出来的一个数据结构,其中包含文件名称、子目录(如果存在的话)和关联的inode等信息。

    dentry结构体最为关键,其维护了内核中的文件目录树。其中里面比较重要的几个结构体分别是d_name、d_hash和d_subdirs。其中d_name代表一个路径节点的名称(文件夹名称)、d_hash则用于构建哈希表,d_subdirs则是下级目录(或文件)的列表。这样,通过dentry就可以形成一个非常复杂的目录树。

    4.2 文件处理流程

    文件处理流程包括两步:

    1)我们在访问一个文件之前首先要打开它(open)文件访问

    2)然后进行文件的读写操作(read或者write)

    我们知道,在用户态打开一个文件是返回的是一个文件描述符,其实也就是一个整数值;同时,访问文件也是通过这个文件描述符进行的。那么操作系统是怎么通过这个整数值实现不同类型文件系统的访问呢?不同文件系统的差异其实就是inode中初始化的函数指针的差异

    在Linux操作系统中,文件的打开必须要与进程(或者线程)关联,也就是说一个打开的文件必须隶属于某个进程。

    在linux内核当中一个进程通过task_struct结构体描述,而打开的文件则用file结构体描述,打开文件的过程也就是对file结构体的初始化的过程。在打开文件的过程中会将inode部分关键信息填充到file中,特别是文件操作的函数指针。在task_struct中保存着一个file类型的数组,而用户态的文件描述符其实就是数组的下标。这样通过文件描述符就可以很容易到找到file,然后通过其中的函数指针访问数据。

    我们以Ext2文件系统的写数据为例来看看文件处理流程和各个层级之间的关系,如下图:

     在调用用户态的写数据接口的时候,需要传入文件描述符。内核根据文件描述符找到file,然后调用函数接口(file->f_op->write)文件磁盘数据。其中file结构体的f_op指针就是在打开文件的时候通过inode初始化的。

    五. 总结

    Linux支持了很多种类的文件系统,包含本地文件系统ext3ext4到网络文件系统NFSHDFS等,VFS系统屏蔽了不同文件系统的操作差异和实现细节,提供了统一的实现框架,也提供了标准的操作接口,这大大降低了操作文件和接入新文件系统的难度。

    参考资料

    展开全文
  • DCTM VFS Provider-开源

    2021-05-02 09:19:18
    用于Documentum的Apache Commons VFS Provider,用于JCommander的插件和用于Apache Mina FTP服务器的VFS
  • 12 VFS

    2020-08-05 21:00:25
    文章目录VFS作用 Linux成功关键之一 与其他操作系统和谐共存。 能透明安装具有其他操作系统文件格式的磁盘或分区, 如Windows、其他版本的Unix, 甚至像 Amiga那样的市场占有率很低 通过虚拟文件系统概念 ...

    • Linux成功的关键因素之一是
      • 它具有与其他OS和谐共存的能力。

    • 你能够透明地安装
      • 具有其他操作系统文件格式的磁盘或分区,
    • 如Windows、其他版本的Unix,
      • 甚至像 Amiga那样的市场占有率很低的系统。

    啥叫安装具有其他操作系统文件格式的磁盘或分区

    • 通过所谓虚拟文件系统概念
    • Linux使用与其他Unix変体相同的方式
      • 设法支持多种文件系统类型。

    一句话: Linux支持多种文件系统类型



    • 虚拟文件系统所隐含的思想是
      • 把表示很多不同种类文件系统的共同信息放入内核;
      • 其中有一个字段或函数来
        • 支持Linux所支持的所有实际文件系统所提供的任何操作。

    • 对所调用的每个读、写或其他函数,
      • 内核都能把它们替换成支持
        • 本地Linux文件系统、
        • NTFS文件系统,
        • 或文件所在的任何其他文件系统的实际函数。


    • 本章讨论Linux虚拟文件系统的设计目标、结构及其实现。

    • 集中讨论五个Unix标准文件类型中的三个文件类型,
      • 普通文件、目录文件和符号链接文件。

    • 设备文件第十三章介绍,
    • 管道文件会在第十九章讨论。

    • 为进一步说明实际文件系统如何工作,
      • 第十八章中对第二扩展文件系统( Second Extended Filesystem)讨论(几乎所有的Linux系统都使用了Ext2)。


    VFS作用

    • 虚拟文件系统也可称之为Virtual Filesystem Switch,VFS),
    • 是一个内核软件层,
    • 用来处理与
      • Unix标准文件系统
      • 相关的所有系统调用。

    • 其健壮性表现在能为各种文件系统提供一个通用接口。


    • 例如,假设一个用户输入以下 shell命令
    • cp /floppy/TEST /tmp/test
    • floppy是MS-DOS磁盘的一个安装点,
    • /tmp是标准的第二扩展文件系统(Ext2)的目录。

    • 图12-1(a),
    • VFS是
      • 用户的应用程序与文件系统实现之间的抽象层。

    • 因此cp程序不需要知道这俩是什么文件系统类型。

    • cp直接与VFS交互,
      • 通过Unix程序设计人员都熟悉的
      • 普通系统调用来进行(第一章“文件操作的系统调用“)。

    • cp的执行代码如图12-1(b)


    • VFS支持的文件系统
      • 可划分为三种主要类型:


    • 磁盘文件系统

    • 这些文件系统
      • 管理在本地磁盘分区中可用的存储空间
      • 其他可起到磁盘作用的设备(USB闪存)。

    • VFS支持的基于磁盘的某些著名文件系统还有:


    • Linux用的文件系统,
      • 广泛使用的第二扩展文件系统(Ext2),
    • 新近的第三扩展文件系统( Third Extended Filesystem,Ext3)
    • 及Reiser文件系统( Reiserfs)(注1)。


    • Unix家族的文件系统,
      • sysv文件系统( System V、 Coherent、 Xenix)、
      • UFS(BSD、 Solaris、 NEXTSTEP),
      • MINIX文件系统及 VERITAS VxFS(SCO Unixware)。

    • 微软公司的文件系统,
      • MS-DOS、VFAT( Windows95及随后的版本)
      • NTFS( Windows NT以及随后的版本)



    • 第一章“Unix文件系统概述“提到,
      • Unix目录建立了一棵根目录为“/“的树。

    • 根目录包含在根文件系统中,
    • Linux中这个根文件系统通常就是Ext2或Ext3类型。

    • 其他所有的文件系统都可以被“安装“在根文件系统的子目录中(注2)。


    • 基于磁盘的文件系统通常存放在硬件块设备中,
      • 如硬盘、软盘或者CD-ROM。

    • Linux VFS的一个有用特点是
      • 能处理如dev/loop0这样的虚拟块设备,
      • 这种设备可用来安装普通文件所在的文件系统。

    • 作为一种可能的应用,用户可保护自己的私有文件系统,
    • 这可通过把自己文件系统的加密版本
      • 存放在一个普通文件中来实现。


    • 第一个虚拟文件系统含在1986年由Sun发布的Sunos中。\

    • 从那时起,
      • 多数Unix文件系统都包含VFS。

    • 然而, Linux的VFS支持最广泛的文件系统。


    通用文件模型

    • VFS所隐含的主要思想在于引入一个通用的文件模型,
      • 这个模型能够表示所有支持的文件系统。

    • 该模型严格反映
      • 传统Unix文件系统提供的文件模型。

    • 这并不奇怪,
      • 因为Linux希望以最小的额外开销运行它的本地文件系统。

    • 不过,要实现每个具体的文件系统,
      • 必须将其物理组织结构转换为虚拟文件系统的通用文件模型。


    • 通用文件模型中,
      • 每个目录被看作一个文件,
      • 可包含若干文件和其他的子目录。

    我的天,神奇了,每个目录还别看成了一个文件!

    • 但存在几个非Unix的基于磁盘的文件系统,
      • 它们利用文件分配表FAT存放每个文件在目录树中的位置,
      • 在这些文件系统中,存放的是目录而不是文件。

    • 为符合VFS的通用文件模型,
      • 对上述基于FAT的文件系统的实现,
      • Linux必须在必要时能够快速建立对应于目录的文件。

    • 这样的文件只作为内核内存的对象而存在。


    • 本质上说, Linux内核不能对一个特定的函数进行硬件编码来执行诸如read()或ioctl()这样的操作,
    • 而是对每个操作都必须用一个指针,
      • 指向要访问的具体文件系统的适当函数


    • 为进一步说明这一概念,见图12-1
    • 显示
      • 内核如何把read()转换为专对MS-DOS文件系统的一个调用。

    • 应用程序对reaa()的调用引起内核调用相应的sys_reaa()服务例程,
      • 这与其他系统调用完全类似。

    • 本章后面看到,
      • 文件在内核内存中是由一个file数据结构来表示。

    • 这种数据结构中含一个称为f_op的字段,
      • 该字段中含一个指向专对MS-DOS文件的函数指针,
      • 当然还包括读文件的函数。

    • sys_read()査找到指向该函数的指针,并调用它。

    • 这样一来,应用程序的read()就被转化为相对间接的调用:

    file->f_op->read(…)

    • 与之类似,
    • write()也引发
      • 一个与输出文件相关的Ext2写函数的执行。

    • 简而言之,
      • 内核负责把一组合适的指针分配给与每个打开文件相关的file变量,
      • 然后负责调用针对
        • 每个具体文件系统的函数(由f_op字段指向)。


    • 你可把通用文件模型看作是面向对象的,
      • 在这里,
      • 对象是一个软件结构,
        • 其中既定义了数据结构也定义了其上的操作方法。

    • 出于效率考虑,
      • Linux的编码未采用面向对象的程序设计语言

    • 对象作为普通的C数据结构来实现,
      • 数据结构中指向函数的字段
        • 对应于对象的方法。


    • 通用文件模型由下列对象类型组成:


    • 超级块对象
    • 存放已安装文件系统的有关信息。

    • 对基于磁盘的文件系统,
      • 这类对象
      • 通常
      • 对应于存放在磁盘上的文件系统控制块


    • 索引节点对象
    • 存放关于具体文件的一般信息。

    • 对基于磁盘的文件系统,
      • 这类对象通常对应于存放在磁盘上的文件控制块。

    • 每个索引节点对象都有一个索引节点号,
      • 唯一标识文件系统中的文件。


    • 文件对象
    • 存放打开文件与进程之间进行交互的有关信息。

    • 这类信息仅当进程访问文件期间存在于内核内存。


    • 目录项对象
    • 存放目录项(也就是文件的特定名称)
    • 对应文件进行链接的有关信息。

    • 每个磁盘文件系统都
      • 以自己特有的方式
      • 将该类信息存在磁盘上。


    • 图12-2说明进程怎样与文件进行交互。

    • 三个不同进程已经打开同一个文件,

      • 两个进程使用同一个硬链接。

    • 这种情况下,
      • 其中的每个进程都使用自己的文件对象,
      • 但只需要两个目录项对象,每个硬链接对应一个目录项对象。

    • 这两个目录项对象指向同一个索引节点对象,
      • 该索引节点对象标识超级块对象,以及随后的普通磁盘文件。


    • VFS除能为所有文件系统的实现
      • 提供一个通用接口外,
    • 还有另一个与系统性能相关的重要作用。

    • 最近最常使用的目录项对象
      • 被放在目录项高速缓存的磁盘高速缓存中,
      • 以加速
        • 从文件路径名
        • 最后一个路径分量的索引节点的转换过程。


    • 一般磁盘高速缓存属软件机制,
      • 它允许内核将原本存在磁盘上的某些信息保存在RAM,


    • 磁盘高速缓存不同于
      • 硬件高速缓存或内存高速缓存,
      • 后两者都与磁盘或其他设备无关。

    • 硬件高速缓存是一个快速静态RAM,它加快了直接对慢速动态RAM的请求(见第二章中的“硬件高速缓存”一节)。

    • 内存高速缓存是一种软件机制,
      • 引入它是为了绕过
      • 内核内存分配器(第八章中的“slab分配器”一节)。


    展开全文
  • vfs基础

    2017-05-18 19:37:21
    2 VFS的概念 VFS是Linux中的一个虚拟文件文件系统,也称为虚拟文件系统交换层(Virtual Filesystem Switch)。它为应用程序员提供一层抽象,屏蔽底层各种文件系统的差异.如下图所示: 3 VFS的构建 所谓VFS的构建就是...
  • Version VFS-开源

    2021-05-02 10:38:47
    该项目的目的是为Linux内核的vfs层中的常规文件提供版本控制支持。 如果使用写标记打开文件,则会创建一个新的文件版本。 尽管更改了内核模式,但仍开发了两个用户工具。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 40,556
精华内容 16,222
关键字:

vfs