《Linux内核设计与实现》第十三章——虚拟文件系统概述

20135211

一、通用文件系统接口

  • 之所以可以使用这种通用接口(VF)对所有类型的文件系统进行操作,是因为内核在它的底层文件系统接口上建立了一个抽象层。
  • 该抽象层使Linux 能够支持各种文件系统。为了支持多文件系统, VFS 提供了一个通用文件系统模型,该模型囊括了任何文件系统的常用功能集和行为。
  • 同时实际文件系统也将自身的诸如“如何打开文件”,“目录是什么”等概念在形式上与VFS 的定义保持一致。

二、Unix文件系统

Unix 使用了四种和文件系统相关的传统抽象概念:文件、目录项、索引节点和安装点

  1. 文件其实可以做一个有序字节串,字节串中第一个字节是文件的头,最后一个字节是文件的

    尾;
  2. 文件通过目录组织起来。文件目录好比一个文件夹,用来容纳相关文件。因为目录也可以包

    含其他目录,即子目录,所以目录可以层层嵌套,形成文件路径;由于VFS 把自录当作文件对待,所以可以对目录执行和文件相同的操作;
  3. Unix 系统将文件的相关信息和文件本身这两个概念加以区分,例如访问控制权限、大小、

    拥有者、创建时间等信息,这些被称作文件的元数据(也就是说,文件的相关数据),被存储在一个单独的数据结构中,该结构被称为索引节点( inode);

三、VFS对象及其数据结构

1. VFS采用的是面向对象的设计思路,使用一组数据结构来代表通用文件对象。包括:

- 超级块对象,它代表一个具体的已安装文件系统。
- 索引节点对象,它代表一个具体文件。
- 目录项对象,它代表一个目录项,是路径的一个组成部分。
- 文件对象,它代表由进程打开的文件。

2. 每个主要对象中都包含一个操作对象,这些操作对象描述了内核针对主要对象可以使用的

方法,操作对象作为一个结构体指针来实现,此结构体中包含指向操作其父对象的函数指针。(其实,对于其中许多方法来说,可以继承使用VFS 提供的通用函数,如果通用函数提供的基本功能无法满足需要,那么就必须使用实际文件系统的独有方法填充这些函数指针,使其指向文件系统实例)

四、超级块对象

  1. 概述:

    1. 各种文件系统都必须实现超级块对象,该对象用于存储特定文件系统的信息,通常对应于存放在磁盘特定扇区中的文件系统超级块或文件系统控制块
    2. 创建、管理和撤销超级块对象的代码位于文件fs/super.c 中。
    3. 超级块对象通过函数alloc_super()创建并初始化。在文件系统安装时,文件系统会调用该函数以便从磁盘读取文件系统超级块,并且将其信息填充到内存中的超级块对象中。
  2. 操作:
    1. 超级块对象中最重要的一个域是s_op,它指向超级块的操作函数表。定义在文件<linux/fs.h>中
    2. 当文件系统需要对其超级块执行操作时,首先要在超级块对象中寻找需要的操作方法;
    3. 由于在C 语言中无法直接得到操作函数的父对象,所以必须将父对象以参数形式传给操作函数;

五、索引结点对象

  1. 索引节点对象包含了内核在操作文件或目录时需要的全部信息;
  2. 一个索引节点代表文件系统中(但是索引节点仅当文件被访问时,才在内存中创建〉的一个

    文件,它也可以是设备或管道这样的特殊文件;
  3. 操作:
    1. 和超级块操作一样,索引节点对象中的inode_operations 项也非常重要,因为它描述了VFS用以操作索引节点对象的所有方搓,这些方能由文件系统实现;
    2. 与超级块类似, 对索引节点的操作调用方式如下:i ->i _op->truncate(i)。其中,i指向给定的索引节点, truncate()函数是由索引节点i 所在的文件系统定义的;

六、目录项对象

  1. 为了方便查找操作, VFS 引入了目录项的概念。每个den世y 代表路径中的一个特定部分;

  2. 目录项也可包括安装点。在路径/mmn/cdrom/foo 中,构成元素/、mmn、foo都属于

    目录项对象。VFS 在执行目录操作时〈如果需要的话)会现场创建目录项对象;

  3. 目录项对象由den町结构体表示,定义在文件<linux/dcacbe.h>中;

  4. 目录项对象有三种有效状态:被使用、未被使用和负状态。

    1. 被使用状态:一个被使用的目录项对应一个有效的索引节点(即d_inode 指向相应的索引节点〉并且表明该对象存在一个或多个使用者(即d_count 为正值〉
    2. 未被使用状态:一个未被使用的目录项对应一个有效的索引节点( d_inode 指向一个索引节点但是应指明VFS 当前并未使用它( d_count )。该目录项对象仍然指向一个有效对象,而且被保留在缓存中以便需要时再使用它;
    3. 一个负状态的目录项没有对应的有效索引节点( d_inode 为NULL ),因为索引节点已被删除了,或路径不再正确。
  5. 目录项缓存

    目的:如果VFS 层遍历路径名中所有的元素并将它们逐个地解析成目录项对象,还要到达最深层目录,将是一件非常费力的工作,会浪费大量的时间。所以内核将目录项对象缓存在目录项缓存(简称dcache )中。

  6. 目录项操作

    1. dentry _operation 结构体指明了VFS 操作目录项的所有方法。该结构定义在文件<lin皿/dcache.h>中:
      • int d_ revalidate(struct dentry *dentry,struct namidata•);该函数判断目录对象是否有效• VFS 准备从dcache 中使用一个目录项肘,会调用该函数。(大部分文件系统将该方法置NULL,因为它们认为dcache 中的目录项对象总是有效的。)
      • int d hash(struct dentry dentry,struct qstr *name);该函数为目录项生成散列值,当目录项需要加入到散列表中肘, VFS 调用该函数。
      • int d_compare(struct dentry •dentry,struct qstr *namel,struct qstr *name2);VFS 调用该函数来比较namel 和name2 这两个文件名
      • int d_dele t e (struct dentry *dentry);当目录项对象的d_count 计数值等于0 时, VFS 调用该函数。注意使用该函数需要加dcache_lock 锁和目录项的d_lock
      • void d_rel ease(struct dentry *dentry);当目录项对象将要被释放时, VFS 调用该函数,默认情况下,它什么也不傲
      • void d_ iput(struct dentry *dentry,struct inode *inode);当一个目录项对象丢失了其相关的索引节点时(也就是说磁盘索引节庚、被删除了), VFS 调用该函数

七、文件对象

  1. 文件对象包含如访问模式, 当前偏移等信息;文件操作常见的系统调用read()、write()等也很类似;
  2. 文件对象仅仅在进程观点上代表已打开文件,它反过来指向目录项对象〈反过来指向索

    引节点〉,其实只有目录项对象才表示巳打开的实际文件。虽然一个文件对应的文件对象不是唯

    一的,但对应的索引节点和目录项对象无疑是唯一的;
  3. 文件操作——具体的文件系统可以为每一种操作做专门的实现,或者如果存在通用操作,也可以使用通用操作

八、文件系统相关的数据结构

  1. 除了以上几种VFS 基础对象外,内核还使用了另外一些标准数据结构来管理文件系统的其他相关数据。第一个对象是file_system_ type, 用来描述各种特定文件系统类型;第二个结构体是vfsmount,用来描述一个安装文件系统的实例。
  2. file_system_ type 结构体被定义在<linux/fs.h>中
    • get_sb()函数从磁盘上读取超级块,并且在文件系统被安装时,在内存中组装超级块对象。剩余的函数描述文件系统的属性。
    • 每种文件系统,不管有多少个实例安装到系统中,还是根本就设有安装到系统中,都只有一个file_system_ type 结构。
  3. vfsmount 结构被定义在<linux/mount.h>中
    • 理清文件系统和所有其他安装点阔的关系,是维护所有安装点链表中最复杂的工作。vfsmount 结构体中维护的各种链表就是为了能够跟踪这些关联信息。

九、和进程相关的数据结构

以下三个数据结构将VFS 层和系统的进程紧密联系在一起

  1. file_ struct 结构体定义在文件<linux/fdtable.h>中。该结构体由进程描述符中的files 目录项指向。所有与单个进程(per-process)的相关的信息〈如打开的文件及文件描述符〉都包含在其中;
  2. fs_struct. 该结构由进程描述符的fs域指向。它包含文件系统和进程相关的信息,定义在文件<linux/fs_ struct.h>中;
  3. 是namespace 结构体=定义在文件<linux/mmt_namespace.h>中,由进程描述符中的mmt_namespace 域指向。2 .4 版内核以后,单进程命名空间被加入到内核中,它使得每一个进程在系统中都看到唯一的安装文件系统一一不仅是唯一的根目录,而且是唯一的文件系统层次结构。

十、总结

Linux支持多种类的操作系统,正是因为vfs的存在,才使得Linux文件系统变得更加简单

《Linux内核分析》第13章的更多相关文章

  1. Linux内核分析第四章 读书笔记

    Linux内核分析第四章 读书笔记 第一部分--进程调度 进程调度:操作系统规定下的进程选取模式 面临问题:多任务选择问题 多任务操作系统就是能同时并发地交互执行多个进程的操作系统,在单处理器机器上这 ...

  2. linux内核分析第3章&第18章读书笔记

    linux内核分析第3章&第18章读书笔记 第三章 进程管理 进程:处于执行期的程序(目标码存放在某种存储介质上) 包含资源:可执行程序代码,打开的文件,挂起的信号,内核内部数据,处理器状态, ...

  3. Linux内核分析——第三章 进程管理

    第三章 进程管理 3.1 进程 1.进程就是处于执行期的程序:进程就是正在执行的程序代码的实时结果:进程是处于执行期的程序以及相关的资源的总称:进程包括代码段和其他资源. 线程:是在进程中活动的对象. ...

  4. Linux内核分析——第五章 系统调用

    第五章 系统调用 5.1 与内核通信 1.系统调用在用户空间进程和硬件设备之间添加了一个中间层,该层主要作用有三个: (1)为用户空间提供了一种硬件的抽象接口 (2)系统调用保证了系统的稳定和安全 ( ...

  5. Linux内核分析第一二章读书笔记

    linux读书笔记(1,2章) 标签(空格分隔): 20135328陈都 第一章 Linux内核简介 Unix的历史 Unix 虽然已经使用了40年,但计算机科学家仍然认为它是现存操作系统中最强大和最 ...

  6. Linux内核分析第三章读书笔记

    第三章 进程管理 3.1 进程 进程就是处于执行期的程序 进程就是正在执行的程序代码的实时结果 线程:在进程中活动的对象.每个线程都拥有一个独立的程序计数器.进程栈和一组进程寄存器. 内核调度的对象是 ...

  7. Linux内核分析——第七章 链接

    第七章——链接 1.链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载到存储器并执行. 2.链接可以执行于编译时,加载时,运行时. 7.1编译器驱动程序 1.大多数编译系 ...

  8. linux内核分析 第4章读书笔记

    第四章 进程调度 一.抢占与非抢占 1.非抢占式进程调度 进程会一直执行直到自己主动停止运行 2.抢占式进程调度 Linux/Unix使用的是抢占式的方式,强制的挂起进程的动作就叫做抢占. 二.进程优 ...

  9. Linux内核分析第四章读书笔记

    第四章 进程调度 进程调度程序:确保进程能有效工作的一个内核子程序 决定将哪个进程投入运行,何时运行已经运行多长时间 进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统 原则:只 ...

  10. Linux内核分析——第四章 进程调度

    第四章 进程调度 4.1 多任务 1.多任务操作系统就是能同时并发的交互执行多个进程的操作系统. 2.多任务操作系统使多个进程处于堵塞或者睡眠状态,实际不被投入执行,这些任务尽管位于内存,但是并不处于 ...

随机推荐

  1. chrony时间服务器

    chrony有着比ntp服务器更好的优势来同步服务,在集群架构中,采用此种服务来同步时间也是最好的方式. 在集群环境中,一般都是一个服务器,然后上百个客户端来同步服务端的时间,接下来我们看看如何配置. ...

  2. <20190303>大厂的风度,firmware每年更新!

    哪怕是最普通的型号, 思科Cisco 每隔一个周期都会推送一个新的firmware, 来提高 路由器的稳定性,和整体兼容性, 2015年买的路由器, 今年年初又发布一个更新包. Release Not ...

  3. FusionCharts参数说明——3D饼图属性(Pie3D.swf )

    animation 是否显示加载图表时的动画palette 内置的图表样式,共5个paletteColors 自定义图表元素颜色(为多个,如过过少会重复)showAboutMenuItem 右键是否显 ...

  4. QT数据类型

    typedef signed char        int8_t;typedef short              int16_t;typedef int                int3 ...

  5. 查询rman 备份信息集

    SELECT TRIM(START_TIME||'#'),       TRIM(END_TIME||'#'),       TRIM(CASE OUTPUT_DEVICE_TYPE         ...

  6. maven中的mirrors

    文章转自http://blog.csdn.net/technologyboy/article/details/17143641 简单点来说,repository就是个仓库.maven里有两种仓库,本地 ...

  7. Jenkins持续集成之小试牛刀

    关于Jenkins的安装,大家可以参考我的这两篇文章: Ubuntu16.04环境安装jenkins docker安装jenkins及其相关问题解决 之前没有好好研究过Jenkins,只是简单学会怎么 ...

  8. Linux系统学习之字符处理

    管道 管道是一种使用非常频繁的通信机制,我们可以使用管道符"|"来连接进程,由管道连接起来订单进程可以自动运行,如同有一个数据流一样,所以管道表现为输入输出重定向的一种方法,它可以 ...

  9. 使用verdaccio 搭建npm私有仓库

    使用verdaccio 搭建npm私有仓库 1. 为什么要搭建私有的npm仓库?    随着公司的业务越来越复杂,项目迭代速度也越来越快,那么项目间的常用的业务代码共享变得非常之有必要.但是对于公司的 ...

  10. 扫盲记-第六篇--Normalization

    深度学习模型中的Normalization 数据经过归一化和标准化后可以加快梯度下降的求解速度,这就是Batch Normalization等技术非常流行的原因,Batch Normalization ...