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.对各个字符由水平排列转为垂直排…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
用递归算法解锁「子集」问题 —— LeetCode 78题解析
文章目录 一、题目介绍二、递归思路详解:从决策树开始理解三、解法一:二叉决策树 DFS四、解法二:组合式回溯写法(推荐)五、解法对比 递归算法是编程中一种非常强大且常见的思想,它能够优雅地解决很多复杂的…...
基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究
摘要:在消费市场竞争日益激烈的当下,传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序,探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式,分析沉浸式体验的优势与价值…...
leetcode73-矩阵置零
leetcode 73 思路 记录 0 元素的位置:遍历整个矩阵,找出所有值为 0 的元素,并将它们的坐标记录在数组zeroPosition中置零操作:遍历记录的所有 0 元素位置,将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...
