虚拟文件系统(VFS)

news2024/11/15 11:54:59

        为支持各种本机文件系统,且在同时允许访问其他操作系统的文件,Linux内核在用户进程(或C标准库)和文件系统实现之间引入了一个抽象层。该抽象层称之为虚拟文件系统(Virtual File System),简称VFS。VFS的任务并不简单。一方面,它用来提供一种操作文件、目录及其他对象的统一方法。另一方面,它必须能够与各种方法给出的具体文件系统的实现达成妥协。

图1 用作文件系统抽象的VFS层

1 文件系统类型 

文件系统一般可以分为下面3种。

(1) 基于磁盘的文件系统(Disk-based Filesystem)是在非易失介质上存储文件的经典方法,用以在多次会话之间保持文件的内容。实际上,大多数文件系统都由此演变而来。比如,一些众所周知的文件系统,包括Ext2/3、Reiserfs、FAT和iso9660。

(2)虚拟文件系统(Virtual Filesystem)在内核中生成,是一种使用户应用程序与用户通信的方法。proc文件系统是这一类的最佳示例。它不需要在任何种类的硬件设备上分配存储空间。相反,内核建立了一个层次化的文件结构,其中的项包含了与系统特定部分相关的信息。

(3)网络文件系统(Network Filesystem)是基于磁盘的文件系统和虚拟文件系统之间的折中。这种文件系统允许访问另一台计算机上的数据,该计算机通过网络连接到本地计算机。在这种情况下,数据实际上存储在一个不同系统的硬件设备上。

2 通用文件模型

        VFS不仅为文件系统提供了方法和抽象,还支持文件系统中对象(或文件)的统一视图。VFS提供一种结构模型,包含了一个强大文件系统所应具备的所有组件。但该模型只存在于虚拟中,必须使用各种对象和函数指针与每种文件系统适配。所有文件系统的实现都必须提供与VFS定义的结构配合的例程,以弥合两种视图之间的差异。当然,虚拟文件系统的结构并非是幻想出来的东西,而是基于描述经典文件系统所使用的结构。VFS抽象层的组织显然也与Ext2文件系统类似。

        在处理文件时,内核空间和用户空间使用的主要对象是不同的。对用户程序来说,一个文件由一个文件描述符标识。该描述符是一个整数,在所有有关文件的操作中用作标识文件的参数。文件描述符是在打开文件时由内核分配,只在一个进程内部有效。两个不同进程可以使用同样的文件描述符,但二者并不指向同一个文件。基于同一个描述符来共享文件是不可能的。

        内核处理文件的关键是inode。每个文件(和目录)都有且只有一个对应的indoe,其中包含元数据(如访问权限、上次修改的日期,等等)和指向文件数据的指针。但inode并不包含一个重要的信息项,即文件名,这看起来似乎有些古怪。通常,假定文件名称是其主要特征之一,因此应该被归入用于管理文件的对象(inode)中。

2.1 inode

2.1.1 基本概念

        如何用数据结构表示目录的层次结构?如前所述,inode对文件实现来说是一个主要的概念,但它也用于实现目录。换句话说,目录只是一种特殊的文件,它必须正确地解释。inode的成员可能分为下面两类。

① 描述文件状态的元数据。例如,访问权限或上次修改的日期。
② 保存实际文件内容的数据段(或指向数据的指针)。就文本文件来说,用于保存文本。

2.1.2 举个栗子        

        为阐明如何用inodes来构造文件系统的目录层次结构,我们来考察内核查找对应于/usr/bin/ emacs的inode过程。

        查找起始于inode,它表示根目录/,对系统来说必须总是已知的。该目录由一个inode表示,其数据段并不包含普通数据,而是根目录下的各个目录项。这些项可能代表文件或其他目录。每个项由两个成员组成。

① 该目录项的数据所在inode的编号。
② 文件或目录的名称。

        系统中所有inode都有一个特定的编号,用于唯一地标识各个inode。文件名和inode之间的关联即通过该编号建立。

(1)查找操作中的第一步是查找子目录usr的inode。这一步会扫描根inode的数据段,直至找到一
个名为usr的目录项(如果查找失败,则返回File not found错误)。相关的inode可以根据inode编号定位。

(2)重复上述步骤,但这一次在usr对应inode的数据段中查找名为bin的目录项,以便根据其inode编号定位inode。下一步在bin的inode数据段中,将查找名为emacs的目录项。这仍然会返回一个inode编号,这一次的inode表示文件而非目录。图8-2给出了查找过程结束时的情形(所经由的路径由对象之间的指针表示)。

(3)最后一个inode的文件内容,与前三个inode不同。前三个inode都表示目录,其文件内容是目录项的一个列表,包括子目录和文件。与emacs文件关联的inode,其数据段存储了文件的内容。

图2 查找/usr/bin/emacs的操作

2.2 链接

        链接(link)用于建立文件系统对象之间的联系。linux中有两种类型的链接,分别是符号链接(软链接)与硬链接。

        符号链接可以认为是“方向指针”(至少从用户程序来看是这样),表示某个文件存在于特定的位置。当然我们都知道,实际的文件在其他地方。符号链接可以认为是一个目录项,其中除了指向文件名的指针,并不存在其他数据。目标文件删除时,符号链接仍然继续保持。对每个符号链接都使用了一个独立的inode。相应inode的数据段包含一个字符串,给出了链接目标的路径。

        对于符号链接,可以区分原始文件和链接。对于硬链接,情况不是这样。在硬链接已经建立后,无法区分哪个文件是原来的,哪个是后来建立的。在硬链接建立时,创建的目录项使用了一个现存的inode编号。删除符号链接并不困难,但硬链接的处理有一点技巧。

        我们假定硬链接(B)与原始文件(A)共享同一个inode。一个用户现在想要删除A。这通常会销毁相关的inode连同其数据段,以便释放存储空间供后续使用。那么接下来B就不能继续访问了,因为相关的inode和文件信息不再存在了。当然,这不是我们想要的行为。在inode中加入一个计数器,即可防止这种情况。每次对文件创建一个硬链接时,都将计数器加1。如果其中一个硬链接或原始文件被删除(不可能区分这两种情况),那么将计数器减1。只有在计数器归0时,我们才能确认该inode不再使用,可以从系统删除。

2.3 编程接口

        用户进程和内核的VFS实现之间的接口照例由系统调用组成,其中大多数涉及对文件、目录和一般意义上的文件系统的操作。对上述的操作,内核提供了50多个系统调用。我们只考察最重要的调用,以阐明关键原则。

        文件使用之前,必须用open或openat系统调用打开。在成功打开文件之后,内核向用户层返回一个非负的整数。这种分配的文件描述符起始于3。我们知道,尽管没有明确规定,这个标识符号之所以不从0开始,是因为所有的进程都分配了前3个标识符(0~2)。0表示标准输入,1表示标准输出,2表示标准错误输出。

        在文件已经打开后,其名称就没什么用处了。它现在由其文件描述符唯一标识,所有其他库函数都需要传递文件描述符作为一个参数(进一步传递到系统调用)。尽管传统上文件描述符在内核中足以标识一个文件,但现在情况不再如此。由于多个命名空间和容器的引入,具有相同数值的多个文件描述符可以共存于内核中。对文件的唯一表示由一个特殊的数据结构(struct file)提供,我将在下文讨论。我们在示例程序调用close的部分会看到文件描述符,该调用关闭与文件的“连接”(释放文件描述符,以便在后续打开其他文件时使用)。 read也需要将文件描述符作为第一个参数,以标识读取数据的来源。

        在一个打开文件中的当前位置保存在文件位置指针(file pointer)中,这是一个整数,指定了当前位置与文件起始点的偏移量。对随机存取文件而言,该指针可以设置为任何值,只要不超出文件存储容量范围即可。这用于支持对文件数据的随机访问。其他文件类型,如命名管道或字符设备的设备文件,不支持这种做法。它们只能从头至尾顺序读取。在文件打开时,可以指定各种标志(如O_RDONLY),用来规定文件的存取模式。

2.4 将文件作为通用接口

        UNIX是基于少量审慎选择的范型而建立的。一个非常重要的隐喻贯穿内核的始终(特别是VFS),尤其是在有关输入和输出机制的实现方面。

万物皆文件

        好,我们承认:当然该规则有少数例外(例如,网络设备),但大多数内核导出、用户程序使用的函数都可以通过VFS定义的文件接口访问。以下是使用文件作为其主要通信手段的一部分内核子系统: 

  • 字符和块设备;
  • 进程之间的管道;
  • 用于所有网络协议的套接字;
  • 用于交互式输入和输出的终端。

        要注意,上述的某些对象不一定联系到文件系统中的某个项。例如,管道是通过特殊的系统调用生成,然后由内核在VFS的数据结构中管理,管道并不对应于一个可以用通常的rm、ls等命令访问的真正的文件系统项。我们特别感兴趣的是访问块设备和字符设备的设备文件。这些是真正的文件,通常位于/dev目录。其内容是在进行读写操作时由相关的设备驱动程序动态生成的。 

3 VFS的结构

        既然我们已经熟悉了VFS的基本结构和用户接口,下面我们将重点讨论其实现细节。在VFS接口的实现中,涉及大量数据结构,有些非常冗长。因此最好草拟出各个组成部分的一个大体概观,并说明其联结方式。

图3 各个VFS组件的相互关系

未完待续 ... 

参考书目:

《深入Linux内核架构》 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/736161.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

git HEAD detached from

git HEAD detached from 解决,checkout切换分支即可,比如切换到master分支: git checkout master git gerrit code review提交代码HEAD:resf/for/_res/for的提交格式_zhangphil的博客-CSDN博客git gerrit code review提交代码HEAD:resf/for/如…

《 SVG 》三、SVG 图形元素

一、本文概述 本文所介绍 svg 元素&#xff0c;为常用 svg 图形元素&#xff0c;蕴含 “血与肉” 的元素&#xff0c;本文围绕其进行实战应用&#xff1b; 二、 SVG 图形元素 <circle> 绘制正圆&#xff1b;<ellipse> 绘制椭圆&#xff1b;<image> 渲染图…

2023通感一体化系统架构与关键技术白皮书

1 通感一体化业务与性能指标 1.1 通感一体化业务分类 根据通信与感知的相互关系 通信辅助感知类业务&#xff1a;通信的参考信号作为感知信号&#xff0c;实现目标定位、测速、手势识别等业务——高速可靠的通信能力为感知数据的汇聚提供保障&#xff0c;能够进一步提高感知精…

人工智能时代如何加强网络安全

人工智能正在为软件开发人员赋予以前被认为难以想象的新能力。新的生成式人工智能可以提供复杂、功能齐全的应用程序、调试代码或使用简单的自然语言提示添加内嵌注释。 它已准备好以指数方式推进低代码自动化。但与此同时&#xff0c;新一代人工智能可能会为不良行为者提供帮…

Spring MVC多种情况下的文件上传

一、原生方式上传 上传是Web工程中很常见的功能&#xff0c;SpringMVC框架简化了文件上传的代码&#xff0c;我们首先使用JAVAEE原生方式上传文件来进行详细描述&#xff1a; 1.1 修改web.xml项目版本 这里我们创建新的SpringMVC模块&#xff0c;在web.xml中将项目从2.3改为3.1…

SPSS数据排序

1.个案排序 &#xff08;1&#xff09;打开数据文件&#xff0c;选择“数据”——“个案排序”&#xff0c;弹出如下图所示的对话框&#xff0c;选中“树高”&#xff0c;再选择排序&#xff08;默认&#xff09; &#xff08;2&#xff09;选中“枝下高”&#xff0c;移到右边…

【IDEA】IDEA 版 Postman 新版发布,功能强大!

介绍 Restful Fast Request 是 IDEA 版 Postman&#xff0c;它是一个强大的 restful api 工具包插件&#xff0c;可以根据已有的方法帮助您快速生成 url 和 params。Restful Fast Request API 调试工具 API 管理工具 API 搜索工具。它有一个漂亮的界面来完成请求、检查服务…

智慧校园管理系统前台任意文件上传

如果沉醉满足于自己以往的历史就无异于生命大限的终临&#xff0c;人生旅程时刻处于“零公里”处。那么&#xff0c;要旨仍然应该是首先战胜自己&#xff0c;并将精神提升到不断发展着的生活所要求的那种高度&#xff0c;才有可能使自己重新走出洼地&#xff0c;亦步亦趋跟着生…

如何在Windows 11中轻松恢复意外删除的Chrome书签

当您意外删除了 Chrome 书签或书签文件夹时&#xff0c;您可以通过以下方法在 Windows 11 中恢复它们。Windows 11 中的 Chrome 浏览器提供了方便的恢复功能&#xff0c;让您可以轻松还原被删除的书签。 打开 Chrome 浏览器并导航到右上角的菜单按钮&#xff0c;点击打开菜单选…

ROS1到ROS2迁移教程(以rslidar_to_velodyne功能包为例)+ ROS2版本LIO-SAM试跑

一、引言 1、本博文主要目的是将rslidar_to_velodyne功能包的ros1版本转换为ros2版本 2、内容会包含ROS1到ROS2迁移技巧&#xff0c;是自己总结的一套简单的流程&#xff0c;可以保证ROS2下的代码试跑成功&#xff0c;如果需要将代码进一步转化为类的实现的方式&#xff0c;自…

开源教育对话大模型 EduChat

文章目录 一、&#x1f680; 前言二、&#x1f916; 本地部署三、&#x1f468;‍&#x1f4bb; 使用示例四、&#x1f50e; 总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、&#x1f680; 前言 教育是一项对人类身心发展产生影响的社会实践…

Elasticsearch 8.X 聚合查询下的精度问题及其解决方案

1、线上环境问题 咕泡同学提问&#xff1a;我在看runtime文档的时候做个测试&#xff0c; agg求avg的时候不管是double还是long&#xff0c;数据都不准确&#xff0c;这种在生产环境中如何解决啊&#xff1f; 2、问题归类及出现场景 上述问题可以归类为&#xff1a;Elasticsear…

【计算机组成与体系结构Ⅰ】实验3 微程序控制器实验

一、实验目的 了解微程序控制器的组成原理 二、实验设备 TEC-4实验系统、万用表 三、实验内容 1&#xff1a;阅读微指令格式和微程序控制器的组成&#xff0c;微指令由操作控制和顺序控制两部分组成&#xff0c;1条微指令的字长35位&#xff08;一个存储单元35位&#xff0c;采…

xml建模----详细完整,易懂结合代码分析

目录 一.XML建模是什么 二.XML建模有什么作用&#xff1f;&#xff1f;&#xff1f; 三.XML建模的案例 以config.xml为例 一.XML建模是什么 将XML配置文件中的元素、属性、文本信息转换成对象的过程叫做XML建模 二.XML建模有什么作用&#xff1f;&#xff1f;&#xff1f; …

Git命令操作【全系列】

Git常用命令操作 1 基础命令 ①git config --global user.name [‘你的用户名’]&#xff1a;查看/设置 git config --global user.name ziyi&#xff1a;设置用户名为ziyi git config --global user.name&#xff1a;查看用户名 ②git config --global user.email [‘你的邮…

React 在Dva项目中修改路由配置,并创建一个自己的路由

之后的话 我们还是来看一下Dva路由的配置 首先 我们在项目刚创建完 他就给了我们一个路径 叫routes 然后 IndexPage.js 是最初的一个组件 之前我们也用过了 然后 我们看到 src目录下的 index.js 这里 就有一个路由的匹配 他加载的就是 同目录下 一个 router的文件 我们点开…

外币兑换----贪心1 (爱思创)

源代码 #include <bits/stdc.h> using namespace std; int main() {double money,maxn-1,r;cin>>money;for(int i1;i<12;i){cin>>r;maxnmax(maxn,money*r);}printf("%0.2f",maxn);return 0; }

阿里云通义万相官网申请地址

通义万相刻削生千变&#xff0c;丹青图“万相”。我是通义万相&#xff0c;一个不断进化的AI绘画创作模型https://wanxiang.aliyun.com/现在申请的人少 应该好通过吧

软考高级之系统架构师系列之系统配置与性能评价、信息化基础

系统配置与性能评价 性能 计算机系统的性能一般包括两个大的方面&#xff1a; 可用性&#xff0c;也就是计算机系统能正常工作的时间&#xff0c;其指标可以是能够持续工作的时间长度&#xff0c;也可以是在一段时间内&#xff0c;能正常工作的时间所占的百分比处理能力&…

MySQL练习题(3)

创建数据库插入数据 CREATE TABLE emp ( empno int(4) NOT NULL, ename varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, job varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, mgr int(4) NULL DEFAULT N…