虚拟文件系统:VFS

http://blog.csdn.net/kickxxx/article/details/9468761

http://blog.csdn.net/flagonxia/article/details/4379586


除了linux标准的文件系统Ext2/Ext3/Ext4外,存在很多种文件系统,比如reiserfs, xfs, Windows的vfat NTFS,网络文件系统nfs 以及flash 文件系统jffs2, yaffs/yaffs2 ubifs。linux通过叫做VFS的中间层最这些文件系统提供了完美的支持。

对于用户来说,这些文件系统是几乎透明的,在大部分情况下,用户通过libc和kernel的VFS交互,不需要关心底层文件系统实现,但是有时应用程序也需要考虑底层文件系统限制(比如fat vfat不支持链接,比如各个文件系统支持最大文件限制不同)。

VFS存在的意义

1. 向上对应用层提供一个标准的文件操作接口;

2. 对下向文件系统提供一个灵活的接口,以便其他操作系统的文件系统可以方便的移植到Linux上;

3. VFS内部则通过系列高效的管理机制,比如inode cache, dentry cache 以及文件系统的预读等技术,使得底层文件系统不需沉溺到复杂的内核操作,即可获得高性能;

4. 此外VFS把一些复杂的操作分尽量抽象到VFS内部,使得底层文件系统实现更简单。


虚拟文件系统包括:【/dev/】、【/proc/】和【/sys/】等,它们下面的任何文件都不会占有硬盘的空间,因为虚拟文件系统只是一个抽象的对应方式,并没有任何实体的文件存在硬盘中。 它的作用是什么?虚拟文件系统作为User Space与Kernel Space之间的桥梁,当用户的应用程序(Application)需要任何的硬件设备时,要先通过虚拟文件系统或系统模块,向Kernel请求支持。也就是说User Space中的应用程序无法直接和Kernel Space交互,必须通过中间的虚拟文件系统。


VFS架构图



文件系统分类

文件系统一般可以分为以下几类

1. 磁盘文件系统

这类文件系统数目最多,最常见:ext2/ext3/ext4文件系统;resierfs文件系统 SGI的XFS文件系统;jffs2 yaffs ubifs等flash文件系统;crasmfs squashfs等只读文件系统;fat vfa ntfs等windows文件系统;

这类文件系统大部分都是基于块设备的文件系统,文件系统的数据和元数据都保存在块设备上;flash文件系统略有差别,flash文件系统是位于MTD之上的,

flash文件系统需要处理坏快,垃圾收集,磨损平衡等复杂的功能。f随着SD/MMC卡的普及,以及flash文件系统在可扩展性,启动速度上的先天不足。flash文件系统已经慢慢退出了嵌入式舞台。

cramfs squashfs存在的意义在于简单,高效,稳定(简单的东西自然稳定),在文件系统只读的场景,仍然会被用到。二者的共同特点就是只读,压缩。我们要有这样一个概念,文件系统的复杂来源于写数据,删除,truncate操作,目录添加删除,因此一个只读文件系统远比可读写文件系统简单。最直观的方法就是查看cramfs文件系统实现代码,只有区区两个小文件。

Reiserfs 提出了很多文件系统的新概念,对小文件的读写操作做了很大的优化,当然新概念过多,也是导致可读性可理解性差的原因。此外由于reiserfs的作者Hans reiserfs因为杀妻罪名成立,所以reiserfs的开发也受到了影响。

XFS相当的复杂,后面我会单独开一片分析

2. 特别的文件系统

此类文件系统也很常用,他们不是提供常规文件存储和访问,文件系统建立在内存之上,提供特殊的文件系统功能。如proc文件系统,pipe文件系统,以及tmpfs

3. 网络文件系统

包括NFS CODA AFS等网络文件系统


通用文件模型

VFS为底层文件系统提供了抽象,有两种方式提供这种抽象。

1. 提供一个最小的通用模型,使得这个模型支持的功能是所有文件系统的最小交集

2. 提供一个尽量大的通用模型,使得这个模型包含所有文件系统功能的合集。

Linux采用第二种策略来实现VFS,因此VFS封装了底层文件系统的所有功能和抽象,VFS负责把应用层的请求转发给特定的文件系统。

在处理文件时,应用空间和内核空间使用的对象是不同的。对应用程序来说,文件描述符用来表示一个文件,这个文件描述符是打开文件时内核分配给这个文件的一个整数,注意,这个文件描述符只在本进程内有效;而对于内核来说,则使用一个inode来表示一个文件,这个inode可能对应着应用层多个进程内的多个文件描述符。


inode

内核中的每一个文件或者目录都有一个inode,inode由两个主要部分组成:

1. 描述文件状态的元数据,文件元数据包括文件大小,权限,类型,时间;

2. 文件数据描述,则用来定义文件数据在磁盘上的存放位置。

inode仅仅是文件在内核内存中的表现形式,虽然每个文件都有inode,但是并不是每个文件在磁盘上都有对应磁盘inode,实际上有些文件系统并没有磁盘inode,inode的生成有时要借助文件系统扫描。


链接

链接是unix特有的概念,又分为软链接和硬链接

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

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

并不是所有的文件系统都支持符号链接和硬链接,比如fat, yaffs等文件系统并不支持符号链接。一般来说,没有磁盘目录结构的文件系统肯定不支持硬链接,而没有磁盘inode的肯定不支持链接。

软硬链接虽然为linux/unix操作管理带来了很多便利,但是在很多软件实现上,往往引入很大的复杂性。


VFS 对象类型

VFS通用模型包含以下类型对象:

1. super block

存储文件系统相关的信息,对于磁盘文件系统来说,这个对象通常对应磁盘上的一个文件系统控制块(磁盘super block)

2. inode

存储一个文件相关的信息,对于磁盘文件系统,这个对象通常对应磁盘上的一个文件控制块(磁盘inode)。每一个inode都对应一个编号,可以在文件系统内唯一标识这个文件。

3. file

file是和进程相关的,file代表一个打开的文件,file和inode之间是多对一的关系,因为多个进程可以打开同一个文件,系统会为每一次打开都创建一个file结构。

4. dentry

底层文件系统的许多操作严重依赖文件的inode,在进行文件操作前,我们需要根据路径名找到文件对应的inode。我们知道文件系统是树状结构的,因此需要从根目录通过目录树找到要操作的文件或目录,这个遍历过程涉及到磁盘操作,非常耗时。根据局部性原理,很有必要把这个查找过程cache起来,dentry就是为了加快目录遍历操作引入的数据结构。

每一个基于磁盘的文件系统,都有特定的方法用来构建目录树。一般来说有两种方式:

1. 磁盘上保存着目录项

2. 通过磁盘文件的父子关系重建目录项


2.1 基本的设备文件

      在/dev/目录下的每个设备文件都有两个代码,即Major Number和Minor Number,它们才是在系统中唯一标识一个设备的识别代码。

     使用ls -l命令,就能看到设备文件的Major Number和Minor Number。如:

     [root@airhouse dev]# ls -l sd*
     brw-r----- 1 root disk 8,  0 2009-07-26 20:44 sda
     brw-r----- 1 root disk 8,  1 2009-07-26 12:45 sda1
     brw-r----- 1 root disk 8,  2 2009-07-26 20:44 sda2
     brw-r----- 1 root disk 8, 16 2009-07-26 20:44 sdb
     brw-r----- 1 root disk 8, 17 2009-07-26 20:44 sdb1
     brw-r----- 1 root disk 8, 18 2009-07-26 20:44 sdb2
     brw-r----- 1 root disk 8, 19 2009-07-26 12:45 sdb3

2.2 /dev/bus

      在/dev目录中,可以根据不同的总线(bus)将硬件分类,目前使用总线访问的存储器,大概都是USB设备。因此在/dev/bus目录中只有一个子目录usb。 我的系统中USB控制器只有一个,它的设备文件是:

       [root@airhouse 001]# pwd

      /dev/bus/usb/001
      [root@airhouse 001]# ls -l
      total 0
      crw-r--r-- 1 root root 189, 0 2009-07-26 20:44 001

2.3 /dev/disk

      该目录下存放所有连接到这台主机上的硬盘信息,按不同的分类方式供用户查询。

      以by-uuid为例,可以看到目前有两只硬盘。

       [root@airhouse by-path]# cd ../by-uuid

      [root@airhouse by-uuid]# ls -l
      total 0
     lrwxrwxrwx 1 root root 10 2009-07-26 12:44 81c97ca6-1d1e-4a5b-903d-bc76ae32a60a -> ../../sda1
     lrwxrwxrwx 1 root root 10 2009-07-26 12:44 dd86b7da-90bb-4b4a-80b8-35afa41cdfef -> ../../sdb3

2.4 /dev/input

      这是存放输入设备的目录,但一般常用的事键盘和鼠标文件。统一的文件时event,但鼠标通用的文件是/dev/input/mice。

 2.5 /dev/mapper

      每个逻辑卷(LV)都在/dev/mapper有一个文件。它们存放实际LV使用的硬盘信息,然后通过device mapper的支持模块来访问硬盘。

      这个目录下还有一个control文件,它是Device Mapepr的控制文件。

 2.6 /dev/net

      目录中默认只会有一个tun设备文件,它是用来建立VPN的“tunnel”所使用的。

 2.7 /dev/pts

      /dev/pts目录下的文件,都是当用户通过非本机登录时,产生出可使用的Terminal界面。它与文件ptmx有直接关系。

 2.8 /dev/shm

      shm是Linux专门用来分享内存的一种API,通过shm的机制,方便地让内存直接变成一种可让用户读写数据的使用空间。

      启动时系统默认会将/dev/shm的目录以tmpfs的文件系统格式挂载(它也是一个VFS)。所以当你使用mount命令可以看到下面一行信息。

                tmpfs on /dev/shm type tmpfs (rw)

       进入系统后,我们自己也可以mount一个tmpfs目录。如:

       [root@airhouse mnt]# mkdir /mnt/tmpfs

      [root@airhouse mnt]# mount -t tmpfs -o size=50M /dev/tmpfs /mnt/tmpfs

       在需要高速存取的场合可以使用它,但是注意,不要使用超过内存大小的空间。

2.9 /dev/.udev

      存放通过udev建立起来的设备文件。udev的工作原理可见我另一篇博文《udev的介绍》。

 2.10 /dev/VolGroup00

      这个目录是在你使用了逻辑卷时才会有。里面存放的是指向该VG包含的LV的设备文件链接。如我的系统里这个文件夹里的东西看上去是这样的。

[root@airhouse VolGroup00]# ls -l
total 0
lrwxrwxrwx 1 root root 31 2009-07-26 20:44 LogVol00 -> /dev/mapper/VolGroup00-LogVol00
lrwxrwxrwx 1 root root 31 2009-07-26 20:44 LogVol01 -> /dev/mapper/VolGroup00-LogVol01
lrwxrwxrwx 1 root root 31 2009-07-26 20:44 LogVol02 -> /dev/mapper/VolGroup00-LogVol02




  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录 1 虚拟文件系统概述 5 1.1 通用文件模型 7 1.2 VFS所处理的系统调用 9 2 虚拟文件系统架构 11 2.1 VFS对象数据结构 11 2.1.1 超级块对象 11 2.1.2 索引节点对象 15 2.1.3 文件对象 18 2.1.4 目录项对象 22 2.2 把Linux中的VFS对象串联起来 24 2.2.1 与进程相关的文件 25 2.2.2 索引节点高速缓存 29 2.2.3 目录项高速缓存 30 2.2.4 VFS对象的具体实现 32 2.3 文件系统的注册与安装 38 2.3.1 文件系统类型注册 38 2.3.2 文件系统安装数据结构 41 2.3.3 安装普通文件系统 52 2.3.4 分配超级块对象 58 2.3.5 安装根文件系统 60 2.3.6 卸载文件系统 65 2.4 路径名的查找 66 2.4.1 查找路径名的一般流程 67 2.4.2 父路径名查找 82 2.4.3 符号链接的查找 84 2.5 VFS系统调用的实现 88 2.5.1 open()系统调用 88 2.5.2 read()和write()系统调用 96 2.5.3 close()系统调用 97 3 第二扩展文件系统 99 3.1 Ext2磁盘数据结构 101 3.1.1 磁盘超级块 102 3.1.2 组描述符和位图 105 3.1.3 磁盘索引节点表 105 3.2 VFS接口数据结构 110 3.2.1 Ext2 超级块对象 110 3.2.2 Ext2 的索引节点对象 121 3.2.3 创建Ext2文件系统 124 3.2.4 Ext2的方法总结 126 3.3 Ext2索引节点分配 129 3.3.1 创建索引节点 130 3.3.2 删除索引节点 143 3.4 Ext2数据块分配 144 3.4.1 数据块寻址 145 3.4.2 文件的洞 147 3.4.3 分配数据块 148 4 页面高速缓存 160 4.1 页高速缓存数据结构 160 4.1.1 address_space对象 161 4.1.2 基树 164 4.2 高速缓存底层处理函数 166 4.2.1 查找页 166 4.2.2 增加页 168 4.2.3 删除页 173 4.3 文件系统与高速缓存 175 4.3.1 缓冲头数据结构 175 4.3.2 分配块设备缓冲区页 178 4.3.3 释放块设备缓冲区页 184 4.4 在页高速缓存中搜索块 185 4.4.1 __find_get_block()函数 185 4.4.2 __getblk()函数 188 4.4.3 __bread()函数 190 4.5 把脏页写入磁盘 191 4.5.1 pdflush内核线程 192 4.5.2 搜索要刷新的脏页 193 4.5.3 回写陈旧的脏页 196 5 文件读写 199 5.1 系统调用VFS层的处理 200 5.2 第二扩展文件系统Ext2层的处理 201 5.2.1 Ext2的磁盘布局 202 5.2.2 Ext2的超级块对象 206 5.2.3 Ext2索引节点对象的创建 210 5.2.4 Ext2索引节点对象的读取 218 5.2.5 Ext2层读文件入口函数 225 5.3 页高速缓存层的处理 237 5.3.1 创建一个bio请求 238 5.3.2 得到文件的逻辑块号 244 5.3.3 普通文件的readpage方法 251 5.3.4 块设备文件的readpage方法 252 5.3.5 文件的预读 260 5.4 通用块层的处理 264 5.4.1 块设备的基础知识 265 5.4.2 通用块层相关数据结构 269 5.4.3 提交I/O传输请求 271 5.4.4 请求队列描述符 273 5.5 块设备I/O调度层的处理 281 5.5.1 块设备的初始化 284 5.5.2 建立块设备驱动环境 288 5.5.3 关联block_device结构 295 5.5.4 为设备建立请求队列 306 5.5.5 块设备I/O调度程序 311 5.5.6 真实的I/O调度层处理 321 5.6 块设备驱动层的处理 330 5.6.1 scsi总线驱动的初始化 330 5.6.2 scsi设备驱动体系架构 342 5.6.3 scsi块设备驱动层处理 347 5.6.4 scsi命令的执行 369 5.6.5 scsi命令的第一次转变 372 5.6.6 scsi命令的第二次转变 380 5.7 写文件 384 5.7.1 generic file_write函数 384 5.7.2 普通文件的prepare_write方法 386 5.7.3 块设备文件的prepare_write方法 387 5.7.4 将脏页写到磁盘 388 6 直接I/O与异步I/O 391 6.1 直接I/O 391 6.2 异步I/O 393 6.2.1 Linux 2.6中的异步I/O 394 6.2.2 异步I/O环境 394 6.2.3 提交异步I/O操作 395

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值