首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

VFS文件系统结构分析

VFS文件系统结构分析

VFS是Linux非常核心的一个概念,linux下的大部分操作都要用到VFS的相关功能。这里从使用者的角度,对VFS进行了简单说明。使用者不但需要知道Linux下有哪些文件操作的函数,还需要对VFS的结构有一个比较清晰的了解,才能更好的使用它。例如hard link 与symbolic,如果没有VFS结构的相了解,就无法搞清楚如何使用它们。
        本文首先是建立了一个简单的目录模型,然后介绍该目录在VFS的结构,最终总结出如何使用各个文件操作函数。
        本着简单使用的原则,主要使用了分析加猜测的方法。鉴于本人水平有限,文中不免会有些错误。欢迎各位读者理性阅读,大胆批判。您的批判是我进步的动力。
        目录
        1 目录模型
        2 VFS的概念
        3 VFS的构建
        4 VFS的结构
        5 Dentry cache
        6 无denty时定位文件
        7 有dentry时定位文件
        8 Symbolic link
        9 hard link
        10 进程对文件的管理
        11 open的过程
        12 open与dup
        13 Fork对打开文件的影响
        14 文件操作函数解析
        1 目录模型        以下面的目录为例。

       


        dir为第一级目录,dir中有subdir0与subdir1两个子目录与一个文件file0。“subdir0”中有两个文件file1与file0。subdir1中有一个文件file3。


        2 VFS的概念        VFS是Linux中的一个虚拟文件文件系统,也称为虚拟文件系统交换层(Virtual Filesystem Switch)。它为应用程序员提供一层抽象,屏蔽底层各种文件系统的差异。如下图所示:

       


        不同的文件系统,如Ext2/3、XFS、FAT32等,具有不同的结构,假如用户调用open等文件IO函数去打开文件,具体的实现会非常不同。为了屏蔽这种差异,Linux引入了VFS的概念。相当于是Linux自建了一个新的贮存在内存中的文件系统。所有其他文件系统都需要先转换成VFS的结构才能为用户所调用。
        3 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节点。

        下图是第一节中的目录模型在VFS中的结构。


       


        5 Dentry cache        每个文件都要对应一个inode节点与至少一个dentry项。假设我们有一个100G的硬盘,上面写满了空文件,那个需要多少内存才能重建VFS呢?
        文件最少要占用1个block(一般是4K)。假一个dentry与一个inode需要100byte,则dentry与inode需要占用1/40的空间。1G硬盘则需要2.5G空间。最近都开始换装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


                       
        然后,根据通过根据subdir0对应的inode号重建inode2,并通过文件数据(目录也是文件)与inode2重建subdir0的dentry节点:dentry1。
继承事业,薪火相传
返回列表