当前位置: 首页 > news >正文

Linux开发讲课47--- 详解 Linux 中的虚拟文件系统

        虚拟文件系统是一种神奇的抽象,它使得 “一切皆文件” 哲学在 Linux 中成为了可能。

        什么是文件系统?根据早期的 Linux 贡献者和作家 Robert Love 所说,“文件系统是一个遵循特定结构的数据的分层存储。” 不过,这种描述也同样适用于 VFAT(虚拟文件分配表Virtual File Allocation Table)、Git 和Cassandra(一种 NoSQL 数据库)。那么如何区别文件系统呢?

        文件系统基础概念

Linux 内核要求文件系统必须是实体,它还必须在持久对象上实现 open()read() 和 write() 方法,并且这些实体需要有与之关联的名字。从 面向对象编程 的角度来看,内核将通用文件系统视为一个抽象接口,这三大函数是“虚拟”的,没有默认定义。因此,内核的默认文件系统实现被称为虚拟文件系统(VFS)。

        如果我们能够 open()read() 和 write(),它就是一个文件,如这个主控台会话所示。

        VFS 是著名的类 Unix 系统中 “一切皆文件” 概念的基础。让我们看一下它有多奇怪,上面的小小演示体现了字符设备 /dev/console 实际的工作。该图显示了一个在虚拟电传打字控制台(tty)上的交互式 Bash 会话。将一个字符串发送到虚拟控制台设备会使其显示在虚拟屏幕上。而 VFS 甚至还有其它更奇怪的属性。例如,它可以在其中寻址。

        我们熟悉的文件系统如 ext4、NFS 和 /proc 都在名为 file_operations 的 C 语言数据结构中提供了三大函数的定义。此外,个别的文件系统会以熟悉的面向对象的方式扩展和覆盖了 VFS 功能。正如 Robert Love 指出的那样,VFS 的抽象使 Linux 用户可以轻松地将文件复制到(或复制自)外部操作系统或抽象实体(如管道),而无需担心其内部数据格式。在用户空间这一侧,通过系统调用,进程可以使用文件系统方法之一 read() 从文件复制到内核的数据结构中,然后使用另一种文件系统的方法 write() 输出数据。

        属于 VFS 基本类型的函数定义本身可以在内核源代码的 fs/*.c 文件 中找到,而 fs/ 的子目录中包含了特定的文件系统。内核还包含了类似文件系统的实体,例如 cgroup、/dev 和 tmpfs,在引导过程的早期需要它们,因此定义在内核的 init/ 子目录中。请注意,cgroup、/dev 和 tmpfs 不会调用 file_operations 的三大函数,而是直接读取和写入内存。

        下图大致说明了用户空间如何访问通常挂载在 Linux 系统上的各种类型文件系统。像管道、dmesg 和 POSIX 时钟这样的结构在此图中未显示,它们也实现了 struct file_operations,而且其访问也要通过 VFS 层。

        VFS 是个“垫片层”,位于系统调用和特定 file_operations 的实现(如 ext4 和 procfs)之间。然后,file_operations 函数可以与特定于设备的驱动程序或内存访问器进行通信。tmpfs、devtmpfs 和 cgroup 不使用 file_operations 而是直接访问内存。

        VFS 的存在促进了代码重用,因为与文件系统相关的基本方法不需要由每种文件系统类型重新实现。代码重用是一种被广泛接受的软件工程最佳实践!唉,但是如果重用的代码引入了严重的错误,那么继承常用方法的所有实现都会受到影响。

                /tmp:一个小提示

        找出系统中存在的 VFS 的简单方法是键入 mount | grep -v sd | grep -v :/,在大多数计算机上,它将列出所有未驻留在磁盘上,同时也不是 NFS 的已挂载文件系统。其中一个列出的 VFS 挂载肯定是 /tmp,对吧?

        为什么把 /tmp 留在存储设备上是不可取的?因为 /tmp 中的文件是临时的(!),并且存储设备比内存慢,所以创建了 tmpfs 这种文件系统。此外,比起内存,物理设备频繁写入更容易磨损。最后,/tmp 中的文件可能包含敏感信息,因此在每次重新启动时让它们消失是一项功能。

        不幸的是,默认情况下,某些 Linux 发行版的安装脚本仍会在存储设备上创建 /tmp。如果你的系统出现这种情况,请不要绝望。按照一直优秀的 Arch Wiki 上的简单说明来解决问题就行,记住分配给 tmpfs 的内存就不能用于其他目的了。换句话说,包含了大文件的庞大的 tmpfs 可能会让系统耗尽内存并崩溃。

        另一个提示:编辑 /etc/fstab 文件时,请务必以换行符结束,否则系统将无法启动。

                /proc 和 /sys

        除了 /tmp 之外,大多数 Linux 用户最熟悉的 VFS 是 /proc 和 /sys。(/dev 依赖于共享内存,而没有 file_operations 结构)。为什么有两种呢?让我们来看看更多细节。

        procfs 为用户空间提供了内核及其控制的进程的瞬时状态的快照。在 /proc 中,内核发布有关其提供的设施的信息,如中断、虚拟内存和调度程序。此外,/proc/sys 是存放可以通过 sysctl 命令配置的设置的地方,可供用户空间访问。单个进程的状态和统计信息在 /proc/<PID> 目录中报告。

  /proc 文件的行为说明了 VFS 可以与磁盘上的文件系统不同。一方面,/proc/meminfo 包含了可由命令 free 展现出来的信息。另一方面,它还是空的!怎么会这样?事实是当进程从 /proc 请求数据时内核再收集有关内存的统计信息,而且当没有人查看它时,/proc 中的文件实际上没有任何内容。

        procfs 的空文件是有道理的,因为那里可用的信息是动态的。sysfs 的情况则不同。让我们比较一下 /proc 与 /sys 中不为空的文件数量。

        

        procfs 只有一个不为空的文件,即导出的内核配置,这是一个例外,因为每次启动只需要生成一次。另一方面,/sys 有许多更大一些的文件,其中大多数由一页内存组成。通常,sysfs 文件只包含一个数字或字符串,与通过读取 /proc/meminfo 等文件生成的信息表格形成鲜明对比。

        sysfs 的目的是将内核称为 “kobject” 的可读写属性公开给用户空间。kobject 的唯一目的是引用计数:当删除对 kobject 的最后一个引用时,系统将回收与之关联的资源。然而,/sys 构成了内核著名的“到用户空间的稳定 ABI”,它的大部分内容在任何情况下都没有人能“破坏”。但这并不意味着 sysfs 中的文件是静态,这与易失性对象的引用计数相反。

        内核的稳定 ABI 限制了 /sys 中可能出现的内容,而不是任何给定时刻实际存在的内容。列出 sysfs 中文件的权限可以了解如何设置或读取设备、模块、文件系统等的可配置、可调参数。逻辑上强调 procfs 也是内核稳定 ABI 的一部分的结论,尽管内核的文档没有明确说明。

        sysfs 中的文件确切地描述了实体的每个属性,并且可以是可读的、可写的,或两者兼而有之。文件中的“0”表示 SSD 不可移动的存储设备。

                        用 eBPF 和 bcc 工具一窥 VFS 内部

        了解内核如何管理 sysfs 文件的最简单方法是观察它的运行情况,在 ARM64 或 x86_64 上观看的最简单方法是使用 eBPF。eBPF(扩展的伯克利数据包过滤器extended Berkeley Packet Filter)由在内核中运行的虚拟机组成,特权用户可以从命令行进行查询。内核源代码告诉读者内核可以做什么;而在一个启动的系统上运行 eBPF 工具会显示内核实际上做了什么。

        令人高兴的是,通过 bcc 工具入门使用 eBPF 非常容易,这些工具在主要 Linux 发行版的软件包 中都有,并且已经由 Brendan Gregg 给出了充分的文档说明。bcc 工具是带有小段嵌入式 C 语言片段的 Python 脚本,这意味着任何对这两种语言熟悉的人都可以轻松修改它们。据当前统计,bcc/tools 中有 80 个 Python 脚本,使得系统管理员或开发人员很有可能能够找到与她/他的需求相关的已有脚本。

        要了解 VFS 在正在运行中的系统上的工作情况,请尝试使用简单的 vfscount 或 vfsstat 脚本,这可以看到每秒都会发生数十次对 vfs_open() 及其相关的调用。

        作为一个不太重要的例子,让我们看一下在运行的系统上插入 USB 记忆棒时 sysfs 中会发生什么。

        在上面的第一个简单示例中,只要 sysfs_create_files() 命令运行,trace.py bcc 工具脚本就会打印出一条消息。我们看到 sysfs_create_files() 由一个 kworker 线程启动,以响应 USB 棒的插入事件,但是它创建了什么文件?第二个例子说明了 eBPF 的强大能力。这里,trace.py 正在打印内核回溯(-K 选项)以及 sysfs_create_files() 创建的文件的名称。单引号内的代码段是一些 C 源代码,包括一个易于识别的格式字符串,所提供的 Python 脚本引入 LLVM 即时编译器(JIT) 来在内核虚拟机内编译和执行它。必须在第二个命令中重现完整的 sysfs_create_files() 函数签名,以便格式字符串可以引用其中一个参数。在此 C 片段中出错会导致可识别的 C 编译器错误。例如,如果省略 -I 参数,则结果为“无法编译 BPF 文本”。熟悉 C 或 Python 的开发人员会发现 bcc 工具易于扩展和修改。

        插入 USB 记忆棒后,内核回溯显示 PID 7711 是一个 kworker 线程,它在 sysfs 中创建了一个名为 events 的文件。使用 sysfs_remove_files() 进行相应的调用表明,删除 USB 记忆棒会导致删除该 events 文件,这与引用计数的想法保持一致。在 USB 棒插入期间(未显示)在 eBPF 中观察 sysfs_create_link() 表明创建了不少于 48 个符号链接。

        无论如何,events 文件的目的是什么?使用 cscope 查找函数 __device_add_disk() 显示它调用 disk_add_events(),并且可以将 “mediachange” 或 “ejectrequest” 写入到该文件。这里,内核的块层通知用户空间该 “磁盘” 的出现和消失。考虑一下这种检查 USB 棒的插入的工作原理的方法与试图仅从源头中找出该过程的速度有多快。

                只读根文件系统使得嵌入式设备成为可能

        确实,没有人通过拔出电源插头来关闭服务器或桌面系统。为什么?因为物理存储设备上挂载的文件系统可能有挂起的(未完成的)写入,并且记录其状态的数据结构可能与写入存储器的内容不同步。当发生这种情况时,系统所有者将不得不在下次启动时等待 fsck 文件系统恢复工具 运行完成,在最坏的情况下,实际上会丢失数据。

        ro-rootfs 提供了许多优点,虽然这些优点不如耐用性那么显然。一个是,如果 Linux 进程不可以写入,那么恶意软件也无法写入 /usr 或 /lib。另一个是,基本上不可变的文件系统对于远程设备的现场支持至关重要,因为支持人员拥有理论上与现场相同的本地系统。也许最重要(但也是最微妙)的优势是 ro-rootfs 迫使开发人员在项目的设计阶段就决定好哪些系统对象是不可变的。处理 ro-rootfs 可能经常是不方便甚至是痛苦的,编程语言中的常量变量经常就是这样,但带来的好处很容易偿还这种额外的开销。

        理解 Linux 内部结构看似是一项不可能完成的任务,因为除了 Linux 用户空间应用程序和 glibc 这样的 C 库中的系统调用接口,内核本身也包含大量代码。取得进展的一种方法是阅读一个内核子系统的源代码,重点是理解面向用户空间的系统调用和头文件以及主要的内核内部接口,这里以 file_operations 表为例。file_operations 使得“一切都是文件”得以可以实际工作,因此掌握它们收获特别大。顶级 fs/ 目录中的内核 C 源文件构成了虚拟文件系统的实现,虚拟文件​​系统是支持流行的文件系统和存储设备的广泛且相对简单的互操作性的垫片层。通过 Linux 命名空间进行绑定挂载和覆盖挂载是 VFS 魔术,它使容器和只读根文件系统成为可能。结合对源代码的研究,eBPF 内核工具及其 bcc 接口使得探测内核比以往任何时候都更简单。

相关文章:

Linux开发讲课47--- 详解 Linux 中的虚拟文件系统

虚拟文件系统是一种神奇的抽象&#xff0c;它使得 “一切皆文件” 哲学在 Linux 中成为了可能。 什么是文件系统&#xff1f;根据早期的 Linux 贡献者和作家 Robert Love 所说&#xff0c;“文件系统是一个遵循特定结构的数据的分层存储。” 不过&#xff0c;这种描述也同样适用…...

全球银行常用英语

Earn OCBC$ or 90 Miles or VOYAGE Miles today! Get the most out of your OCBC Card with OCBC Privileges. 今天赚取华侨银行美元或 90 英里或航程英里&#xff01;通过华侨银行特权充分利用您的华侨银行卡。 Check out the rewards catalogue. Apply for a OCBC Credit Car…...

新160个crackme -090-tc.12

运行分析 需要破解注册码 PE分析 Delphi程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 ida搜不到字符串&#xff0c;根据Deiphi程序的结构&#xff0c;直接打开来到start函数&#xff0c;找到CreateForm函数的参数off_445FC4&#xff0c;双击 逐个查找偏移&…...

Swagger文档-Unable to scan documentation context default报错

文章目录 报错情况&#xff1a; Unable to scan documentation context 管理端接口发生情况一&#xff1a;发生情况三&#xff1a; 报错情况&#xff1a; Unable to scan documentation context 管理端接口 报错日志&#xff1a; 2024-11-03 12:40:27.427 ERROR 3340 --- [ …...

SpringKafka生产者、消费者消息拦截

1 前言 在Spring Kafka中&#xff0c;可以通过配置拦截器来实现对生产者和消费者消息的拦截。拦截器可以用来记录日志、修改消息等等。 2 基于Kafka管理的拦截器 Kafka原生提供的拦截器接口是org.apache.kafka.clients.producer.ProducerInterceptor和 org.apache.kafka.cli…...

Qt报错QOCI driver not loaded且QOCI available的解决方法

参考 Linux Qt 6安装Oracle QOCI SQL Driver插件&#xff08;适用WSL&#xff09; 安装 QOCI 插件完成后运行 Qt 项目报错&#xff1a; qt.sql.qsqldatabase: QSqlDatabase: QOCI driver not loaded qt.sql.qsqldatabase: QSqlDatabase: available drivers: QMIMER QPSQL QODBC…...

python mac vscode 脚本文件的运行

切换到脚本文件的目录下 路径的修改 当前文件组织形式&#xff1a; 脚本文件在文件夹下&#xff1a; 赋予权限&#xff1a;chmod x ./scripts/fscd_test.sh 运行&#xff1a;./scripts/fscd_test.sh...

Linux之du命令

华子目录 du命令常用选项示例注意事项 du命令 du&#xff08;Disk Usage&#xff09;命令是用于在类Unix操作系统&#xff08;如Linux和macOS&#xff09;中显示文件和目录所占用的磁盘空间大小的工具。它可以递归地计算目录和文件的磁盘使用情况&#xff0c;并提供详细的报告…...

WRF-LES与PALM微尺度气象大涡模拟

针对微尺度气象的复杂性&#xff0c;大涡模拟&#xff08;LES&#xff09;提供了一种无可比拟的解决方案。微尺度气象学涉及对小范围内的大气过程进行精确模拟&#xff0c;这些过程往往与天气模式、地形影响和人为因素如城市布局紧密相关。在这种规模上&#xff0c;传统的气象模…...

桌面程序开发框架选择

桌面程序开发框架选择 1、WinForm(Windows Form)优点缺点 2、WPF(Windows Presentation Foundation)优点缺点 3、Electron优点缺点 4、Delphi优点缺点 5、QT优点缺点 6、MFC(Microsoft Foundation Class Library)优点缺点 7、JavaFX优点缺点 8、SwingAWT9、Avalonia10、Flutter…...

Vue项目开发:Vuex使用,表单验证配置,ESLint关闭与常见问题解决方案

文章目录 vuexvue配置form表单验证移除vue中表单验证的两种方法关闭vue项目的eslint代码校验做vue项目出现的问题 vuex Vue提供的状态管理工具&#xff0c;用于统一管理我们项目中各种数据的交互和重用&#xff0c;存储我们需要用到的数据对象属性 state&#xff1a;vuex的基本…...

源鲁杯2024赛题复现Web Misc部分WP

MISC [Round 1] whatmusic 拿到题目&#xff0c;一个password和加密的压缩包 查看password的文件尾 这里会发现是png文件的文件头&#xff0c;逆序输出&#xff0c;并保存为1.png。得到一个图片&#xff0c; 进行CRC爆破&#xff0c;发现宽高被修改&#xff0c;之后拿到压缩…...

【企业微信新版sdk】

wecom 的引入使用 一、引入wecom二、封装函数三、使用测试 一、引入wecom 1、企业微信 WECOM-JSSDK提供了 npm 和 cdn 两种引入途径。1.1、 npm 引入 npm install wecom/jssdk1.2、安装后引入 import * as ww from wecom/jssdk通过 script 标签引入 <script src"ht…...

web安全测试渗透案例知识点总结(下)——小白入狱

目录 [TOC](目录)一、更多详细的实际案例教程案例1&#xff1a;文件上传漏洞利用案例2&#xff1a;目录遍历&#xff08;Path Traversal&#xff09;漏洞检测案例3&#xff1a;暴力破解登录密码案例4&#xff1a;命令注入漏洞案例5&#xff1a;身份认证绕过&#xff08;Passwor…...

【专题】数据库的安全性

1. 数据库安全性概述 数据库存在的不安全因素&#xff1a; 非授权用户对数据库的恶意存取和破坏&#xff1b; 数据库中重要或敏感的数据被泄露&#xff1b; 安全环境的脆弱性。 数据库的安全性与计算机系统的安全性&#xff0c;包括计算机硬件、操作系统、网络系统等的安全…...

【含开题报告+文档+源码】基于Java的房屋租赁服务系统设计与实现

开题报告 随着城市化进程的加速和人口流动性的增加&#xff0c;租房需求不断增长。传统的租赁方式往往存在信息不对称、流程不规范等问题&#xff0c;使得租户和房东的租赁体验不佳。而而房屋租赁系统能够提供便捷、高效的租赁服务&#xff0c;满足租户和房东的需求。房屋租赁…...

数据结构模拟题[十]

数据结构试卷&#xff08;十&#xff09; 一、选择题 (24 分) 1&#xff0e;下列程序段的时间复杂度为&#xff08; &#xff09;。 i0 &#xff0c;s0&#xff1b; while (s<n) {ssi &#xff1b;i &#xff1b;} (A) O(n 1/2 ) (B) O(n 1/3 ) (C) O(n) (D) O(n 2 ) …...

Java基于微信小程序的美食推荐系统(附源码,文档)

博主介绍&#xff1a;✌程序猿徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…...

基于CNN-RNN的影像报告生成

项目源码获取方式见文章末尾&#xff01; 600多个深度学习项目资料&#xff0c;快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【PaddleNLP的FAQ问答机器人】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…...

MacOS如何读取磁盘原始的扇区内容,恢复误删除的数据

MacOS 也是把磁盘当成一个文件&#xff0c;也是可以使用 dd来读取&#xff0c;命行令行如下&#xff1a; sudo dd if/dev/disk2 bs512 count1 skip100 ofsector_100.bin 这个就是读取 /dev/disk2这个磁盘每100这个sector, bs表示扇区大小是512. 但是你直接用读&#xff0c;应…...

OpenClaw语音控制之语音命令识别系统架构详解

5.1 系统架构总览5.1.1 整体架构OpenClaw 语音命令识别系统是一个基于事件驱动的实时语音处理平台&#xff0c;核心设计目标是实现低延迟、高可靠的语音交互能力。系统采用模块化架构&#xff0c;各组件通过明确定义的接口进行通信&#xff0c;支持多种电话服务提供商&#xff…...

从‘猫狗大战’到医疗影像:LRP(逐层相关性传播)如何帮医生看懂AI的‘诊断思路’?

从‘猫狗大战’到医疗影像&#xff1a;LRP如何成为医生与AI的翻译官 当一位放射科医生第一次看到AI系统标注的肺结节"恶性概率92%"时&#xff0c;他的反应不是赞叹&#xff0c;而是皱眉&#xff1a;"它凭什么这么判断&#xff1f;"这种场景正在全球各大医院…...

在Jetson Nano上构建海康威视相机Docker镜像:从SDK集成到Python应用部署

1. 环境准备与基础配置 在Jetson Nano上构建海康威视相机Docker镜像的第一步&#xff0c;是确保硬件和基础软件环境就绪。我建议从官方渠道下载最新的JetPack SDK&#xff0c;这个工具包包含了CUDA、cuDNN等深度学习推理必需的组件。安装完成后&#xff0c;记得运行nvidia-smi命…...

别再死记硬背!用Python(SymPy库)自动推导DC-DC变换器的小信号模型

用Python解放双手&#xff1a;SymPy自动推导DC-DC变换器小信号模型的工程实践 当电源工程师面对Buck、Boost电路的小信号模型推导时&#xff0c;那些繁琐的矩阵运算和拉普拉斯变换是否让你头疼不已&#xff1f;传统手工推导不仅耗时费力&#xff0c;还容易在代数运算中出错。本…...

超实用AI专著生成攻略,掌握工具技巧,轻松搞定大型学术著作

学术专著创作困境与AI写作工具解决方案 撰写学术专著时的困难&#xff0c;不仅仅体现在“能够写出来”&#xff0c;更关键的是“能够成功出版并获得认可”。在当今的出版行业&#xff0c;学术专著的受众群体相对较小&#xff0c;出版社在选择题材时&#xff0c;对其学术价值以…...

告别混乱标注!手把手教你定制LabelImg的标注框颜色与样式(附打包exe完整流程)

视觉标注效率革命&#xff1a;LabelImg高级定制与团队部署实战指南 在计算机视觉项目的标注环节中&#xff0c;混乱的视觉呈现往往成为效率瓶颈。当标注员面对数百张包含"车辆"、"行人"、"交通标志"等多类别的图像时&#xff0c;系统随机分配的标…...

nli-distilroberta-base轻量化效果实测:在嵌入式设备上的推理性能与精度

nli-distilroberta-base轻量化效果实测&#xff1a;在嵌入式设备上的推理性能与精度 1. 开篇&#xff1a;当大模型遇上小设备 在树莓派上跑BERT&#xff1f;半年前这还是个笑话。但当我第一次在Jetson Nano上成功运行量化后的nli-distilroberta-base模型时&#xff0c;这个4核…...

告别反复插拔SD卡:迪文DGUS II屏串口下载与仿真调试全攻略(附T5L实战技巧)

告别反复插拔SD卡&#xff1a;迪文DGUS II屏串口下载与仿真调试全攻略&#xff08;附T5L实战技巧&#xff09; 在工业控制、智能家居和物联网设备的开发中&#xff0c;迪文DGUS II系列串口屏因其高性价比和强大的组态功能&#xff0c;已成为众多开发者的首选。然而&#xff0c;…...

记录模式到底要不要在Spring Boot中落地?阿里、蚂蚁内部技术委员会最新评估报告曝光,87%团队已启动灰度迁移

第一章&#xff1a;记录模式在Spring Boot生态中的战略定位与演进脉络 记录模式&#xff08;Recording Mode&#xff09;并非Spring Boot官方术语&#xff0c;而是社区对一类以“可观测性前置”为核心理念的设计范式所形成的共识性称谓——它强调在应用生命周期早期即注入结构化…...

3步搞定浏览器功能扩展:Greasy Fork开源脚本管理平台完全指南

3步搞定浏览器功能扩展&#xff1a;Greasy Fork开源脚本管理平台完全指南 【免费下载链接】greasyfork An online repository of user scripts. 项目地址: https://gitcode.com/gh_mirrors/gr/greasyfork Greasy Fork作为开源的用户脚本管理平台&#xff0c;为技术爱好者…...