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 接口使得探测内核比以往任何时候都更简单。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

海的记忆篇章:海滨学院班级回忆录项目

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了海滨学院班级回忆录的开发全过程。通过分析海滨学院班级回忆录管理的不足&#xff0c;创建了一个计算机管理海滨学院班级回忆录的方案。文章介绍了海滨学院班级回…

【WebRTC】WebRTC的简单使用

目录 1.下载2.官网上的使用3.本地的使用 参考&#xff1a; 【webRTC】一、windows编译webrtc Windows下WebRTC编译 1.下载 下载时需要注意更新python的版本和网络连接&#xff0c;可以先试试ping google。比较关键的步骤是 cd webrtc-checkout set https_proxy127.0.0.1:123…

【05】如何解决tomcat命令提示符控制台乱码问题

Web项目开发过程中&#xff0c;直接在命令提示符窗口中通过输入startup.bat命令运行tomcat&#xff0c;在新弹出的tomcat命令提示符窗口中输出的中文是乱码问题的处理。 如何解决tomcat命令提示符控制台乱码问题 文章目录 如何解决tomcat命令提示符控制台乱码问题1.解决问题思路…

Golang | Leetcode Golang题解之523题连续的子数组和

题目&#xff1a; 题解&#xff1a; func checkSubarraySum(nums []int, k int) bool {m : len(nums)if m < 2 {return false}mp : map[int]int{0: -1}remainder : 0for i, num : range nums {remainder (remainder num) % kif prevIndex, has : mp[remainder]; has {if …

JeecgBoot集成工作流实战教程

Activiti是一个轻量级的工作流程和业务流程管理&#xff08;BPM&#xff09;平台&#xff0c;它主要面向业务人员、开发人员和系统管理员。这个平台的核心是一个快速且可靠的Java BPMN 2流程引擎。Activiti是开源的&#xff0c;并且基于Apache许可证进行分发。它可以运行在任何…

springcloud整合sentinel,限流策略持久化到nacos,详细配置案例

目录 1.组件下载和启动 &#xff08;1&#xff09;sentinel-dashboard下载 &#xff08;2&#xff09;nacos下载 &#xff08;3&#xff09;jmeter下载 &#xff08;4&#xff09;redis下载&#xff08;与流控关系不大&#xff0c;与项目启动有关&#xff09; 2.本微服务项…

利用Docker Compose构建微服务架构

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 利用Docker Compose构建微服务架构 引言 Docker Compose 简介 安装 Docker Compose 创建项目结构 编写 Dockerfile 前端 Dockerf…

Python毕业设计选题:基于大数据的旅游景区推荐系统_django

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 系统首页界面 用户注册界面 用户登录界面 景点信息界面 景点资讯界面 个人中心界面 …

02- 模块化编程-002 DS1302数码显示时间与日期

1、数码显示时间日期的电路 2、电路原理简介 电路组件与功能 单片机&#xff08; PIC16F887&#xff09;&#xff1a; 作为系统的主控芯片&#xff0c;处理所有输入输出&#xff0c;进行时间控制和显示信息更新。 DS1302&#xff08;实时时钟芯片&#xff09;&#xff1a; 用于…

token无感刷新+处理并发的后端方案

问题描述&#xff1a; 当用户通过登陆后进入一个web网站&#xff0c;会把token保存到localStorage。假设token过期时间30min。 那么当用户在网站快乐地玩耍了30min后&#xff0c;这时进行了一次提交表单&#xff0c;它会被重定向到登陆页面。 作为用户&#xff1a;我表单填了…

atoi函数学习

文章目录 一、atoi函数1、函数原型2、函数功能3、函数返回 二、atoi使用三、atoi函数模拟实现 一、atoi函数 1、函数原型 atoi函数参数为一个字符指针&#xff0c;返回类型是int&#xff0c;作用将字符串转换为整型。使用函数需要包含头文件stdlib.h 2、函数功能 解析c字符串…

基于vue框架的的考研信息共享平台v0eyp(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;国家政策,用户,院校政策,院校信息,考研资料,资料分类,考研论坛 开题报告内容 基于Vue框架的考研信息共享平台开题报告 一、研究背景与意义 随着考研人数的逐年增长&#xff0c;考研学生对高效、便捷、个性化的信息获取需求愈发强烈。…

UG NX二次开发(C#)-计算圆柱面与其他平面的夹角

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、首先创建一个三维模型3、 源代码4、调用代码1、前言 在QQ群中,有群友提问了如何判断圆柱面与某一平面是否垂直,我这里以案例的形式计算圆柱面主轴矢量与平面法矢的夹角,如果夹角为0,…

【Linux】IPC进程间通信:并发编程实战指南(一)

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 进程间通信介绍 &#x1f98b; 1.进程通信的目的&#x1f98b; 2.进程通信的方式 二&#xff1a;&#x1f525; 「匿名管道」通信 &#x1f98b; 匿名管道…

数据采集-Kepware OPCUA 服务器实现

KepserverEX OPC UA server设置 系列文章目录 数据采集-Kepware 安装证书异常处理 目录 KepserverEX OPC UA server设置系列文章目录一、OPC UA(OPC Unified Architecture)二、防火墙的配置三、配置KepserverEX的OPC UA3.1 启用远程连接3.2 启动OPCUA服务器接口 四、管理OPCU…

spring-boot(mybatisplus条件构造、接口、生成器)

条件构造器 除了新增以外&#xff0c;修改、删除、查询的SQL语句都需要指定where条件。因此BaseMapper中提供的相关方法除了以id作为where条件以外&#xff0c;还支持更加复杂的where条件。 使用&#xff1a; 第一步创建条件查询&#xff1a; //条件的构造查询 QueryWrapper…

单个相机矫正畸变

1、通过标定助手获取到内参外参&#xff0c;外参在此无效&#xff0c;只用到了内参 2、然后通过halcon算子进行矫正 参考&#xff1a;超人视觉

金华迪加网络科技有限公司现场大屏互动系统存在文件上传漏洞

漏洞描述 金华迪加网络科技有限公司专注于开发和优化现场互动系统平台,其主要产品是现场活动大屏幕系统。这个系统被设计用于增强活动现场的互动性&#xff0c;提供技术支持给合作企业。某公司现场大屏互动系统存在文件上传漏洞&#xff0c;未经身份验证的攻击者通过漏洞上传恶…

构 造 器

我们创建了一个对象&#xff0c;在其中定义了属性&#xff0c;new一个对象&#xff0c;然后设置对应的属性&#xff0c;但是我们可以在new对象的时候&#xff0c;同时传入我们要设置的属性&#xff0c;这个时候就需要构造器。 特点 构造方法是一个特殊的成员方法&#xff0c;…

Android平台RTSP|RTMP播放器高效率如何回调YUV或RGB数据?

技术背景 我们在做Android平台RTSP、RTMP播放器的时候&#xff0c;经常遇到这样的技术诉求&#xff0c;开发者希望拿到播放器解码后的YUV或RGB数据&#xff0c;投递给视觉算法&#xff0c;做AI分析&#xff0c;本文以ffmpeg和大牛直播SDK的SmartPlayer为例&#xff0c;介绍下相…