Linux内核学习(九)—— 虚拟文件系统(基于Linux 2.6内核)
虚拟文件系统(VFS)作为内核子系统,为用户空间程序提供了文件和文件系统相关的接口。通过虚拟文件系统,程序可以利用标准的 Unix 系统调用对不同的文件系统(甚至不同介质上的文件系统)进行读写操作。

一、通用文件系统接口
VFS 可以使得用户可以直接使用 open()、read() 和 write() 等文件相关系统调用,而不需要考虑具体文件系统和实际物理介质。VFS 与块 I/O 相结合,提供抽象、接口,使得用户空间的程序调用统一的系统调用访问各种文件。
二、文件系统抽象层
内核在所有类型的文件系统接口上建立了一个抽象层,该抽象层使 Linux 能够支持各种文件系统。
VFS 之所以能衔接各种各样的文件系统,是因为它定义了所有文件系统都支持的、基本的、概念上的接口和数据结构。而实际的文件系统通过编程提供 VFS 所期望的抽象接口和数据结构,这样,内核就可以毫不费力地连接在一起。
如下面这个例子:
ret = write(fd, buf, len)
该系统调用将 buf 指针指向的长度为 len 字节的数据写入文件描述符 fd 对应的文件的当前位置。这个系统调用首先执行 sys_write() 系统调用函数,该函数要找到 fd 所在的文件系统所实现的写操作,然后再执行该操作,数据最终通过该操作写入介质。

三、Unix 文件系统
Unix 有四种与文件系统相关的传统抽象概念:文件、目录项、索引节点和挂载点(mount point)。
从本质上讲文件系统是特殊的数据分层存储结构,它包含文件、目录和相关的控制信息。文件系统的通用操作包含创建、删除和挂载等。在 Unix 中,文件系统被安装到一个特定的挂载点上,该挂载点在全局层次结构中被称为命名空间,所有的已安装文件系统都作为根文件系统树的枝叶出现在系统中。
VFS 把目录当作文件对待,所以可以对目录执行和文件相同的操作。
Unix 系统将文件的相关信息和文件本身这两个概念加以区分,例如访问控制权限、大小、拥有者等信息。文件相关信息也被称作文件的元数据,被存储在一个单独的数据结构中,这个结构被称为索引结点(inode)。文件系统的信息则存储在超级块中,超级块是一种包含文件系统信息的数据结构。
比如说在磁盘上,文件(目录也属于文件)信息按照索引节点的形式存储在单独的块中;控制信息被集中存储在磁盘的超级块中。
四、VFS 对象及其数据结构
VFS 采用的是面向对象的设计思路,使用一组数据结构来代表通用文件对象。这些结构体包含数据的同时也包含操作这些数据的函数指针,其中的操作函数由具体的文件系统实现。
VFS 有四个主要的对象类型,分别是:
- 超级块对象,代表一个具体的已安装文件系统。、
- 索引节点对象,它代表一个具体文件。
- 目录项对象,它代表一个目录项,是路径的一个组成部分(注:目录项不同于目录,目录属于文件对象)。
- 文件对象,它代表由进程打开的文件。
上述每个对象都包含一个对应的操作对象,这些操作对象描述了内核针对主要对象可以使用的方法:
- super_operations 对象,包含内核针对特定文件系统能调用的方法,比如 write_inode() 和 sync_fs() 等方法。
- inode_operations 对象,包含内核针对特定文件能调用的方法,比如 create() 和 link()。
- dentry_operations 对象,包含内核针对特定目录所能调用的方法,如 d_compare() 和 d_delete()。
- file_operations 对象,包含进程针对已打开文件所能调用的方法,比如 read() 和 write()。
操作对象作为一个结构体指针来实现,里面包含指向操作其父对象的函数指针。对于其中许多方法来说,可以继承使用 VFS 提供的通用函数,如果通用函数的功能无法满足需要,那么就必须使用实际文件系统独有的方法来填充这些函数指针。
五、超级块对象
各种文件系统都必须实现超级块对象,该对象用于存储特定文件系统的信息,通常对应于存放在磁盘特定扇区中的文件系统超级块或文件系统控制块。对于并非基于磁盘的文件系统(如基于内存的文件系统,sysfs),它们会在使用现场创建超级块并将其保存到内存中。
超级块对象由 super_block 结构体表示,定义在文件 <linux/fs.h> 中:


六、索引节点对象
索引节点对象包含了内核在操作文件或目录时需要的全部信息。索引节点对象与其对应的文件是分开存放的。索引节点对象由 inode 结构体表示,定义在文件 <linux/fs.h> 中:

一个索引节点代表文件系统中的一个文件,它也可以是设备或管道这样的特殊文件。因此索引节点结构体中有一些和特殊文件相关的项,如 i_pipe 项就指向一个代表有名管道的数据结构,i_bdev 指向块设备结构体,i_cdev 指向字符设备结构体。
索引节点对象的 inode_operations 项也非常重要,因为它描述了 VFS 用以操作索引节点对象的所有方法,这些方法由文件系统实现。
inode->inode_operations->对应操作函数

七、目录项对象
VFS 把目录当作文件来对待,所以在路径 /bin/vi 中,bin 和 vi 都属于文件,bin为目录文件而 vi 是一个普通文件,路径中的每个组成部分都由一个索引节点对象表示。
为了方便查找操作,VFS 引入了目录项,每个目录项代表路径中的一个特定部分,如 前面的 /、bin 和 vi 都属于目录项的概念。在路径中的每一个部分都是目录项对象,目录项的引入可以让文件的查找变得更加方便。
目录项对象由 dentry 结构体表示,定义在文件 <linux/dcache.h> 中:

与前面两个对象不同,目录项没有对应的磁盘数据结构,VFS 根据字符串形式的路径名现场创建它。由于目录项并非真正保存在磁盘上,所以目录项结构体没用是否被修改的标志。
目录项有三种有效状态:被使用、未被使用和负状态。
- 一个被使用的目录项对应一个有效的索引节点(即 d_inode 指向相应的索引节点),并且表明该对象存在一个或多个使用者(d_count 为正值)。
- 一个未被使用的目录项对应一个有效的索引节点(d_inode 指向一个索引节点), 但是应指明 VFS 当前并未使用它(d_count 为 0)。该目录项对象仍然指向一个有效对象,而且保留在缓存中以便需要时再使用它,所以之后再需要它时不需要重新创建。
- 一个负状态的目录项(或者说无效目录项)没有对应的有效索引节点(d_inode 为 NULL),因为索引节点已被删除了,或路径不再正确了,但目录项仍保留。
如果 VFS 遍历路径名中所有的元素并将它们逐个地解析成目录项对象,还要达到最深层目录,将是一件非常费力的工作,所以内核将目录项对象缓存再目录项缓存中(简称 dcache),以节省时间。
八、文件对象
文件对象表示进程已打开的文件。该对象由相应的 open() 系统调用创建,由 close() 系统调用撤销。因为多个进程可以同时打开和操作同一个文件,所以同一个文件也可能存在多个对应的文件对象。虽然一个文件对应的文件对象不是唯一的,但对应的索引节点和目录项对象是唯一的。
文件对象由 file 结构体表示,定义在 <linux/fs.h> 中:


类似于目录项对象,文件对象实际上没有对应的磁盘数据,只有当一个文件被进程打开时才被创建。
文件对象的操作如下:


相关文章:
Linux内核学习(九)—— 虚拟文件系统(基于Linux 2.6内核)
虚拟文件系统(VFS)作为内核子系统,为用户空间程序提供了文件和文件系统相关的接口。通过虚拟文件系统,程序可以利用标准的 Unix 系统调用对不同的文件系统(甚至不同介质上的文件系统)进行读写操作。 一、通…...
【模拟】算法实战
文章目录 一、算法原理二、算法实战1. leetcode1576 替换所有的问号2. leetcode495 提莫攻击3. leetcode6 N字形变换4. leetcode38 外观数列5. leetcode1419 数青蛙 三、总结 一、算法原理 模拟就是用计算机来模拟题目中要求的操作,模拟题目通常具有代码量大、操作…...
各个微服务模块之间互相依赖调用的问题
首先是模块之间不能够循环引用,否则会报循环依赖引入的错误。 没有了模块之间的相互依赖,在项目中这两个模块是相互调用的,分别各自定义相应的Feign接口,如下: 最开始写的运行报错的代码如下: FeignCli…...
理论转换实践之keepalived+nginx实现HA
背景: keepalivednginx实现ha是网站和应用服务器常用的方法,之前项目中单独用nginx实现过负载均衡和服务转发,keepalived一直停留在理论节点,加之最近工作编写的一个技术文档用到keepalived,于是便有了下文。 服务组件…...
华为OD七日集训第1期复盘 - 按算法分类,由易到难,循序渐进,玩转OD(文末送书)
目录 一、活动内容如下第1天、逻辑分析第2天、字符串处理第3天、数据结构第4天、双指针第5天、递归回溯第6天、二分查找第7天、贪心算法 && 二叉树 二、可观测性工程1、简介2、主要内容 大家好,我是哪吒。 最近一直在刷华为OD机试的算法题,坚持…...
MPI之持久化通信句柄与非持久化通信句柄
MPI_Isend & MPI_Send 创建临时通信句柄 在前面的文章中举了例子,我们使用MPI_Isend接口发送数据时,有个传出参数request,该参数是创建的通信句柄, 实际上该句柄是一个临时句柄,即只用于一次性发送数据的场景&…...
搭建个人备忘录中心服务memos、轻量级笔记服务
目录 一、源码 二、官网 三、搭建 四、使用 一、源码 GitHub - usememos/memos: A privacy-first, lightweight note-taking service. Easily capture and share your great thoughts. 二、官网 memos - Easily capture and share your great thoughts 三、搭建 docke…...
探究代理技术在网络安全、爬虫与HTTP通信中的多重应用
在当今高度互联的世界中,代理技术在网络安全、爬虫开发以及HTTP通信中扮演着举足轻重的角色。本文将深入探讨Socks5代理、IP代理以及HTTP代理在这些领域中的多重应用,探索其如何为我们创造更安全、高效的网络环境。 1. Socks5代理:构建安全通…...
vue左侧漏斗切换 echart图表动态更新
这个需求是根据点击左侧的箭头部分,右侧图表切换,左侧选中数据高亮(图片用的svg) 一、效果图 二、vue组件 <template><div class"funnel_wrap"><div class"flex_between"><div class&q…...
Centos7安装ZK-UI管理界面安装|Maven|Git|
一: JDK1.8安装 参考: Centos7卸载|安装JDK1.8|Xshell7批量控制多个终端 二:Maven安装 2.1:下载maven安装包 maven 下载地址:https://mirror.bit.edu.cn/apache/maven/maven-3/ [rootwww ~]# mkdir -p /usr/local/maven [rootwww ~]# …...
C语言日常刷题7
文章目录 题目答案与解析1234567 题目 1、如下程序的运行结果是( ) char c[5]{a, b, \0, c, \0}; printf("%s", c)A: ‘a’ ‘b’ B: ab\0c\0 C: ab c D: ab 2、若有定义: int a[2][3]; ,以下选项中对 a 数组元素正确…...
037 - 有关时间和日期的函数方法
文档:MySQL :: MySQL 5.7 Reference Manual :: 12.7 Date and Time Functions 以下为案例,更多内容可查看文档 返回当前日期: CURDATE() 返回当前时间: CURTIME() 返回当前日期和时间: NOW() 返回年份&a…...
(JAVA)树——tree
...
js判断对象是否为空对象的方法总结
js判断对象是否为空对象的方法总结 方法1:JSON.stringify()方法方法2:for in方法方法3:Object.keys()方法方法4:Object.getOwnPropertyNames()方法方法5:jquery 的 isEmptyObject()方法 在面试或者开发过程中ÿ…...
LeetCode1049. 最后一块石头的重量 II
1049. 最后一块石头的重量 II 文章目录 [1049. 最后一块石头的重量 II](https://leetcode.cn/problems/last-stone-weight-ii/)一、题目二、题解方法一:01背包二维数组算法思路具体实现 方法二:01背包一维数组 一、题目 有一堆石头,用整数数…...
universal robot 机械臂 官方基本教程
https://academy.universal-robots.cn/modules/e-Series-core-track/Chinese/module3/story_html5.html?courseId2166&languageChinese 教程1 控制箱内部 包含: 主机板,SD卡,和安全控制板 安全控制板负责所有控制信息,包括…...
网络常见安全漏洞
引言 随着互联网的迅猛发展,网络安全问题日益严重。在网络世界中,各种常见的安全漏洞给人们的通信和数据安全带来了巨大的威胁。本文将介绍一些常见的网络安全漏洞,并提供一些防范措施。 1. XSS(跨站脚本攻击) 跨站…...
【JS案例】JS实现图片放大镜功能
JS案例图片放大镜 🌟效果展示 🌟HTML结构 🌟CSS样式 🌟实现思路 🌟具体实现 1.初始化数据图片 2.获取所需DOM元素 3.初始化页面 初始化缩略图 绑定事件 🌟完整代码 🌟写在最后 &…...
linux centos7 bash中字符串反向输出
给定一个字符串,如何反向(倒序)输出? 字符串反转的方法:a.对各个字符位置进行循环调换(从原字符串左边取出放在新字符串的右边;从原字符串右边取出放在新字符串的左边)。b.对各个字符由水平排列转为垂直排…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...
