【Linux系统编程】文件系统

介绍:

        文件系统是操作系统中负责管理和存储文件信息的软件结构,它组织和管理磁盘上的文件和目录,并定义了文件的存储结构。

        Linux文件系统采用树状结构,只有一个根目录(用“/”表示),其中含有下级子目录或文件的信息。子目录中又可以包含更多的子目录或文件,这样一层一层地延伸下去,构成一棵倒置的树。


磁盘

        进程打开文件,没有打开的文件在磁盘上保存,并通过文件系统进行管理。在笔记本电脑(或任何计算机)中,C盘和D盘(以及其他可能的盘符,如E盘、F盘等)并不是物理硬件本身,而是硬盘或固态硬盘(SSD)上的逻辑分区或卷。这些分区或卷在操作系统中被识别为不同的驱动器或“盘”,并分配了不同的字母标识符(如C:、D:等)。

        在磁盘中,文件属性对应的数据存储在结构体inode中。它包括文件类型、大小、权限、时间等等,但inode没有包含文件名,因为文件名不属于文件属性。Linux中使用ll -i 指令可查看文件或目录的inode。这里要说明的是系统管理文件的属性大小是固定的(内容与属性分开存储),因为属性的类别是一样的,只不过每个类别的内容不一样,即inode大小通常固定,大小通常是128字节,有些的文件系统中可以设置为256字节。


inode结构

inode管理

        inode结构体准确来说记录了文件的元数据信息,是唯一标识文件系统中的每一个文件的。元数据包括文件属性,其中,一个inode可以有多个文件名,但一个文件名只能对应一个inode。

        那么inode具体是如何怎么管理文件的呢?在同一文件系统中,每个inode结构中都存储着一个唯一的编号,即inode编号。操作系统使用inode编号来识别不同的文件,而不是文件名来识别文件。系统都是通过inode来对文件进行操作的。我们通常使用ls -i命令可以查看文件的inode号。

        通常,每个文件或目录都有一个唯一的inode与之关联(一个inode对应一个文件名的情况),但是有些特殊情况下(一个inode对应多个文件名的情况下),多个文件名(文件名也叫硬链接)可能对应同一个inode。这种情况下,所有的这些文件名都会引用同一个inode,并且具有相同的inode编号。这意味着这些文件实际上是同一个文件的不同名称,它们共享相同的文件内容和元数据。需要注意的是,虽然多个文件名可以指向同一个inode,但一个inode通常只能与一个文件内容相关联。也就是说,你不能有两个不同的文件内容共享同一个inode。如果你尝试这样做,系统通常会创建一个新的inode来存储新的文件内容。

        inode在文件系统中存储在磁盘文件系统的分区里的inode表中,即inode Table。

inode链接和inode表

        inode中包含一个链接数(link count),表示有多少个文件名(即硬链接)指向这个inode。当创建一个新的硬链接时,链接数会增加一个;当删除一个硬链接(无论是通过rm命令还是删除目录项)时,链接数会减少一个。当链接数减少到0时,inode会被标记为可回收,对应磁盘空间上的文件内容会被删除。

        这里我们说明一下文件名。Linux系统中,inode本身并不直接存储文件名,而是存储了文件的元数据信息。文件名实际上是与inode关联的目录项中的一部分,具体来说文件名与相应的inode编号关联,它们保存在文件系统的目录结构中。文件名只是一个标识符,真正的文件内容和属性是通过inode来访问的。至于文件内容,inode是通过内部数据块指针来指向的,inode中的数据块指针指向文件内容在磁盘上的存储位置。这些指针是文件系统定位文件内容的关键,不同的文件会有不同的数据块指针分布。

        文件=“文件属性”  + “文件内容”。文件的一系列信息基本都是通过inode间接引出的。总的来说,当系统对文件进行操作时,首先会找到对应inode编号,找到inode编号后就能在inode表(inode Table)中找到inode,找到inode后,就能拿到inode里面对应的文件数据块。


磁盘文件系统

        上图中是磁盘文件系统的分区(如同windows下的C盘、D盘等)。磁盘是典型的块设备,硬盘分区(如上图)被划分为一个个大小固定的block。一个block的大小是由格式化的时候确定的,不可以更改。其中上图的 Boot Block 是启动块。上图的Block group 0......Block group n是一个分区中对应的很多分组。每个分组中又划分了许多个块(Block),下面我们依次来分析这些块。

        inode Table:inode表。从逻辑和概念上讲,可以将inode表(inode Table)视为一个数组,其中每个inode的编号可以看作是这个数组的一个下标。通过inode编号,可找到文件在磁盘上的存储位置。具体有多少个inode是系统根据分区早早分配好的。

        inode Bitmap:inode位图。我们不能确定inode Table(inode表)中的inode是否被占用,系统是通过inode Bitmap(inode位图)使用每个bit来表示一个inode是否空闲可用。比特位的位置表示第几个inode,比特位的内容表示该inode是否被使用(0表示未占用,1表示已被占用)。

        Data blocks:数据块。存放文件内容。Data blocks是由无数的块(block)组成,每个块大小一般固定约4KB,存放文件内容时从左到右依次使用块存储,且每个块都有自己的编号。这些块的数量也是系统根据分区就已分配好的。

        Block Bitmap(Block位图):块位图。记录着Data Blocks中哪个数据块已经被占用,哪个数据块没有被占用。Block Bitmap原理与inode Bitmap一样,都是通过相应编号(即:数组下标)标识是否被用过。

        下面问题来了,系统如何知道哪一个inode和哪一个Date blocks(即文件内容)是对应关系呢?inode内部里面包含了block整型数组,此数组记录了对应文件数据块的编号。即通过inode中的block数组即可找到对应的文件内容。

        例如:当我们新建一个文件并写入文件内容时,在上面四种块结构中,系统首先会在inode Bitmap查找没有使用的位图,这里会通过计数从左到右开始遍历,直到找到未占用的inode(即数组下标为0),然后会在inode Table中进行索引(如在inode位图中找到的是10,直接在inode表中找到第十个inode),接下来会使用inode属性结构体把文件对应的字段填入进入,之后会把这个inode结构体按照二进制形式拷贝到inode Table中对应的inode块中(如拷贝到inode表中第十个inode里),这里属性就有了,至于文件内容的填充取决于内容的大小,若文件内容大小估计使用1个块,即内容小于4KB,这里会分配一个块进行填充,分配的块号会被写入block整型数组中,对应的Block Bitmap也会被修改成1。当清除文件时,这里先找到inode,将对应的inode Bitmap和Block Bitmap位图号从1变成0即可。也就是说删除文件时不会删除inode的内容以及block的内容,只需把对应的两个位图清掉即可。

        现在我们都明白,查找一个文件就是通过inode编号来查找,那么具体是如何快速通过inode编号找到对应的文件呢?我们要先明白inode是在一个分区中唯一的,不是在一个分组中唯一的。倘若在第一个分组中分配10000个inode,即起始值是1,那么第二个分组中分配的inode就会从10001开始,即起始值是10001,后面同理。当系统给文件分配inode编号时,若在一个分区中的第n个分组中对应inode Bitmap找到第m个bit为0,即找到了inode Table中的第m个inode,那么在往第m个inode填充属性时,填充inode字段里的inode编号其实是 “inode Table中的起始偏移量” + m。拿到对应的inode编号查找具体的inode时,首先会在每个分组中分配的inode范围中找到具体对应的分组,然后再用inode编号减去对应分组下的起始inode偏移量就能找到对应的inode Bitmap中的位号和inode Table中具体的inode号,当查到对应inode Bitmap中的位号属于存在位号时,就会在对应的inode Table中找到具体的inode获取属性信息。文件内容同理,只不过在inode对应的block整型数组字段中,眏射的块并不是全部对应的文件内容,而是采用直接索引、间接索引和三级索引或更多的索引通过块来引出,块中存放着指向对应块的指针,指向对应块,但大多数情况下(文件内容较小的情况)block是直接眏射文件内容的。

        Group Descriptor Table(GDT):块组描述符,描述块组属性信息。它也是一个结构体,包含了该分组的具体信息,如inode的数量、空闲inode的数量、数据块的数量、空闲数据块的数量等。因此,每个分组中的GDT大概率都是不一样的,GDT被损坏会导致这个分组被破坏。

        Super Block(超级快):超级块包含了关于文件系统的全局信息,存放文件系统本身的结构信息,包括每个分组的描述块的位置和大小。通过读取超级块,系统可以定位到每个分组的描述块。记录的信息主要有:bolck 和 inode的总量, 未使用的block 和 inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了,因此,虽然整个文件系统的关键信息只需要一个Super Block就足够了,但是系统还会在个别的分组中加入Super Block,而不是全部分组中加入,这样既保证了某个Block Group的Super Block数据损坏,文件系统仍然可以通过其他Block Group中的Super Block备份信息来恢复,也能保证跟新Super Block时的效率问题。总的来说,系统只要拿到了Super Block就可对此分区进行管理。

        Boot Block块比较特殊,它并不是所有分区都拥有的,主要功能是协助系统了解磁盘的分区情况,这里了解即可。

        上面的分区情况就是文件系统下的情况,即一个分区对应一个文件系统。平常电脑上磁盘的格式化本质是向指定的分区中写入全新的文件系统(上面介绍的文件系统属于ext2版本,其它版本的文件系统可能有所不同,但原理都是一样的,只不过增添了一些日志内容)。那么系统如何管理多个文件系统?一个分区一个文件系统,每个分区中的核心是Super Block,里面包含了该分区下的所有属性。系统只需拿到每个分区下的Super Block,然后将它们用链表的形式连接起来即可。总的来说,系统对分区的管理就是对Super Block的管理;系统对多个文件系统的管理就是对链表的管理。


文件名

        了解文件名,首先我们要先了解下目录。任何一个普通文件一定在一个目录中,而目录也是文件,也通过inode管理,但目录的内容放什么呢?目录的数据块中存放的是文件名和inode编号的眏射关系。当在目录中查找一个文件名时,系统能够根据文件名来找到对应的inode。当在目录中创建一个新文件时,将对应的inode和数据块填充之后,系统会拿到对应文件的inode编号的眏射关系和文件名再写入到文件目录内容里面。文件权限的限制功能对应的是以上原理。

        当我们在一个目录中创建一个文件时,若该目录没有写权限,将不能在该目录下创建文件,因为创建文件时需要将该文件的inode编号的眏射关系和文件名再写入到目录内容里,若没有写权限就无法写入。查找文件时同理,若是无法读取文件名与inode编号的眏射关系进而将无法使用对应的功能。删除一个文件时需要去除目录里面的文件名与inode编号的眏射关系,这也需要修改目录内容,这也就是为什么去掉写权限将无法删除文件。其它权限功能同理。

        这里有一个问题,当查找一个文件,我们需要拿到该目录的内容,目录内容在数据块中存储的,要想拿到该目录的内容就要拿到该目录的inode编号,要想拿到该目录的inode编号就要拿到该目录的目录的内容,这样就出现了 “鸡生蛋,蛋生鸡” 的问题,最终会在根目录(“/”)下终止。因此,在系统层面上,当查找一个文件时,在内核中都要逆向的递归般得到根目录,然后系统再从根目录下诼渐往下查找,进行路径解析,直到找到指定文件。查找的过程中系统会把此路径信息缓存下来,方便我们在此路径下对不同目录或文件进行快速切换或操作。

        当我们拿到inode后,又该如何在分区中寻找inode呢?这里我们要先明白挂载的概念。一个被写入文件系统的分区,要被Linux使用,必须要先把这个具有文件系统的分区进行 “挂载” 。“挂载” 是把一个文件系统所对应的分区,挂载在对应的目录中,文件系统的数据结构与目录的数据结构之间通过指针关联,访问分区下的文件系统都是要通过目录来访问。在Linux中使用 df -h 命令可查看。比如我们使用云服务器时,上面左侧Filesystem表示文件系统,服务器上的云盘只有一块,即分区只有一个,叫做/dev/vda1,它被挂载到根目录上。因为只有一个分区,所以从根目录下的所有内容都会在这一个分区中,也就是说要访问此分区,只要保证我们在根目录下,就能访问当前对应的分区。倘若我们系统中存在多盘的情况下,即存在 /dev/vda1、/dev/vda2、/dev/vda3...,这时需要时用mount命令将分区挂载到Linux下的一个文件夹中,从而将分区和该目录联系起来,从此往后只需访问这个文件夹就相当于访问该分区了。挂载好之后使用 df -h 指令可查看到此挂载后的目录,当进行路径切换后,就可能从一个分区切换到另一个分区了,本质就是从一个目录切换到另一个目录。总的来说,分区的访问就是通过所挂载的路径访问的,我们也可使用Linux下的命令来创建文件系统,实现挂载,然后cd到指定的目录后,我们就是在访问这个分区。

        当查找指定的文件时,系统会根据路径最前缀的目录优先判断出该文件在具体哪个分区下,然后根据路径不断往下解析将会找到所有对应的inode。对于路径若不详细说明,系统会默认在当前路径下。最终将指定的文件inode导入内存中,通过进程打开。

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

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

相关文章

【Linux】:程序地址空间

朋友们、伙计们,我们又见面了,本期来给大家解读一下有关Linux程序地址空间的相关知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏:C语言:从…

GD32实战篇-双向数控BUCK-BOOST-BUCK降压理论基础

本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发 向上代码兼容GD32F450ZGT6中使用 后续项目主要在下面该专栏中发布: https://blog.csdn.net/qq_62316532/category_12608431.html?spm1001.2014.3001.5482 感兴趣的点个关注收藏一下吧! 电机驱动开发可以跳转…

【驱动篇】龙芯LS2K0300之ADC驱动

实验目的 由于LS2K0300久久派开发板4.19内核还没有现成可用的ADC驱动,但是龙芯官方的5.10内核已经提供了ADC驱动,想要在4.19内核使用ADC就要参考5.10内核移植驱动,本次实验主要是关于ADC驱动的移植和使用 驱动移植 主要的驱动代码主要有3个…

【面向就业的Linux基础】从入门到熟练,探索Linux的秘密(十二)-管道、环境变量、常用命令

大致介绍了一下管道、环境变量、一些常用的基本命令,可以当作学习笔记收藏学习一下!!! 文章目录 前言 一、管道 二、环境变量 1.概念 2.查看 3.修改 4.常用环境变量 三、系统状况 总结 前言 大致介绍了一下管道、环境变量、一些常…

【数据结构与算法】快速排序霍尔版

💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:《数据结构与算法》 期待您的关注 ​

#数据结构 笔记一

数据结构是计算机存储、组织数据的方式。 数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。数据结构是带有结构特性的数据元素的集合,它研究的是数据的逻辑结构和物理结构以及它们之间的相互关系,并对这种结构定义相适应的运算&#xff0…

STM32实现硬件IIC通信(HAL库)

文章目录 一. 前言二. 关于IIC通信三. IIC通信过程四. STM32实现硬件IIC通信五. 关于硬件IIC的Bug 一. 前言 最近正在DIY一款智能电池,需要使用STM32F030F4P6和TI的电池管理芯片BQ40Z50进行SMBUS通信。SMBUS本质上就是IIC通信,项目用到STM32CubeMXHAL库…

华为机试HJ51输出单向链表中倒数第k个结点

华为机试HJ51输出单向链表中倒数第k个结点 题目: 想法: 因为要用链表,且要找到倒数第k个结点,针对输入序列倒叙进行构建链表并找到对应的元素输出。注意因为有多个输入,要能接受多次调用 class Node(object):def __…

OSS存储桶漏洞总结

简介 OSS,对象存储服务,对象存储可以简单理解为用来存储图片、音频、视频等非结构化数据的数据池。相对于主机服务器,具有读写速度快,利于分享的特点。 OSS工作原理: 数据以对象(Object)的形式…

mac|Mysql WorkBench 或终端 导入 .sql文件

选择Open SQL Script导入文件 在第一行加入use 你的schema名字,相当于选择了这个schema 点击运行即可将sql文件导入database 看到下面成功了即可 这时候可以看看左侧的目标database中有没有成功导入table,如果没有看到的话,可以点一下右上角的…

25_嵌入式系统总线接口

目录 串行接口基本原理 串行通信 串行数据传送模式 串行通信方式 RS-232串行接口 RS-422串行接口 RS-485串行接口 RS串行总线总结 RapidIO高速串行总线 ARINC429总线 并行接口基本原理 并行通信 IEEE488总线 SCSI总线 MXI总线 PCI接口基本原理 PCI总线原理 PC…

CSS【详解】长度单位 ( px,%,em,rem,vw,vh,vmin,vmax,ex,ch )

px 像素 pixel 的缩写,即电子屏幕上的1个点,以分辨率为 1024 * 768 的屏幕为例,即水平方向上有 1024 个点,垂直方向上有 768 个点,则 width:1024px 即表示元素的宽度撑满整个屏幕。 随屏幕分辨率不同,1px …

【大模型LLM面试合集】大语言模型基础_LLM为什么Decoder only架构

LLM为什么Decoder only架构 为什么现在的LLM都是Decoder only的架构? LLM 是 “Large Language Model” 的简写,目前一般指百亿参数以上的语言模型, 主要面向文本生成任务。跟小尺度模型(10亿或以内量级)的“百花齐放”…

SpringBoot运维篇

工程打包与运行 windows系统 直接使用maven对项目进行打包 jar支持命令行启动需要依赖maven插件支持&#xff0c;打包时须确认是否具有SpringBoot对应的maven插件 <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><ar…

最小表示法

#define _CRT_SECURE_NO_WARNINGS #include<bits/stdc.h> using namespace std;const int N (int)3e5 5; int n; int a[N * 2];int main() {cin >> n;for (int i 0; i < n; i) {cin >> a[i];a[i n] a[i]; // 构造成链}int l 0, r 1; // 一开始 r …

昇思12天

FCN图像语义分割 1. 主题和背景 FCN是由UC Berkeley的Jonathan Long等人于2015年提出的&#xff0c;用于实现图像的像素级预测。 2. 语义分割的定义和重要性 语义分割是图像处理和机器视觉中的关键技术&#xff0c;旨在对图像中的每个像素进行分类。它在很多领域有重要应用…

npm安装完yarn还是用不了?

前言 解决 找到你的包全局安装目录 复制路径&#xff0c;配置到Path全局环境变量 结果 不过发现在idea里还是用不了&#xff0c;此时你会想&#xff0c;这什么烂贴&#xff0c;没一点屁用 不过在重启idea之后&#xff0c;你也许就不会这么想了

秋招提前批面试经验分享(下)

⭐️感谢点开文章&#x1f44b;&#xff0c;欢迎来到我的微信公众号&#xff01;我是恒心&#x1f60a; 一位热爱技术分享的博主。如果觉得本文能帮到您&#xff0c;劳烦点个赞、在看支持一下哈&#x1f44d;&#xff01; ⭐️我叫恒心&#xff0c;一名喜欢书写博客的研究生在读…

数据结构/作业/2024/7/7

搭建个场景: 将学生的信息&#xff0c;以顺序表的方式存储&#xff08;堆区)&#xff0c;并且实现封装函数︰1】顺序表的创建&#xff0c; 2】判满、 3】判空、 4】往顺序表里增加学生、5】遍历、 6】任意位置插入学生、7】任意位置删除学生、8】修改、 9】查找(按学生的学号查…

网络安全基础-2

知识点 1.网站搭建前置知识 域名&#xff0c;子域名&#xff0c;DNS&#xff0c;HTTP/HTTPS&#xff0c;证书等 注册购买域名&#xff1a;阿里云企航_万网域名_商标注册_资质备案_软件著作权_网站建设-阿里云 2.web应用环境架构类 理解不同WEB应用组成角色功能架构: 开发语…