深入理解Linux文件系统

                                                           🎬慕斯主页修仙—别有洞天 

                                                         ♈️今日夜电波:晴る—ヨルシカ

                                                                0:20━━━━━━️💟──────── 4:30
                                                                    🔄   ◀️   ⏸   ▶️    ☰  

                                      💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


目录

引入

磁盘的物理存储结构

磁盘存储的逻辑抽象结构

理解文件系统

inode

什么是inode?

inode Table

inode Bitmap

Data blocks

Block Bitmap

Super Block

GDT

Boot Block

对于目录的理解

硬链接和软链接

硬链接

硬链接的应用

软连接


引入

        当我们使用ls -l命令的时候,我们可以看到的除了看到文件名,还看到了文件元数据 。而对于所表示部分的理解,依次分别为:权限部分、链接数、文件所有者、文件所属组、文件的大小、文件的最后修改时间、以及文件名。

        例子:第一行a.out的对应表示:

  • rwxrwxr-x:这是文件权限部分,共有10个字符,分为4组,每组3个字符。第一组表示文件所有者的权限,第二组表示文件所属组的权限,第三组表示其他用户的权限。
    • rwx:表示文件所有者具有读(r)、写(w)和执行(x)权限。
    • rwx:表示文件所属组具有读(r)、写(w)和执行(x)权限。
    • r-x:表示其他用户具有读(r)和执行(x)权限,但没有写(w)权限。
  • 1:表示链接数,这里有一个链接指向该文件。
  • amazon:表示文件所有者的用户名是amazon。
  • amazon:表示文件所属组的用户名是amazon。
  • 8560:表示文件的大小为8560字节。
  • Jan 15 20:57:表示文件的最后修改时间为2022年1月15日20点57分。
  • a.out:表示文件名是a.out。

        当然,如果想查看更详细的有关信息可以使用stat命令

        还是以a.out为例:

        对于以上的解析:

        文件名为'a.out',大小为8560字节,属于普通文件。文件的权限设置为-rwxrwxr-x,表示文件所有者具有读、写和执行权限,文件所属组和其他用户只有读和执行权限。文件的设备号为fd01h/64769d,inode编号为1310801,链接数为1。文件的访问时间是2024年1月15日20点57分22秒395467毫秒,修改时间是2024年1月15日20点57分19秒028325毫秒,更改时间也是2024年1月15日20点57分19秒028325毫秒。文件没有创建时间。

        对于上述的两个例子,我们对于其中的信息大多都是认识的,但是对于Blocks、Inode、Links等却不怎么熟悉,接下来的文章将围绕文件系统的物理到系统来叙述,即:从物理层面的磁盘到系统上的磁盘。以此来了解这些信息的意义。

磁盘的物理存储结构

        由上图可见,一个盘面可以有很多的同心磁道,一圈磁道可以有很多扇形的扇区,而扇区就是最小的存储单元(大概512B或者4KB)。而存储文件的本质就是向这些扇区进行写入!这是通过上电改变磁盘中颗粒的磁极朝向来作为0/1进而看作写入数据,读取也是读取磁极的朝向来看作读取0/1进而读取数据。如果我们想向一个扇区写入,我们如何进行寻址、定位呢?1、选择哪一面盘片—本质上就是选择磁头。2、选择该面上的哪一个磁道。3、选择在该磁道上的哪一个扇区。当然,由于我们是有多个盘片的,我们可以向一个写入,想当然的也可以向任意一个/连续多个扇区写入,也可以随机写入。

磁盘存储的逻辑抽象结构

        通过上面对于物理层面磁盘的理解。接下来我们需要将这个结构抽象到系统中!一个磁盘中有多个盘片,盘片中分为多个磁道,通过一定的划分可以划分为多个扇区(可以理解为从盘片圆心拉出来很多条线,然后其中两条线以及磁道分割出来的区域)。对此我们可以将整个磁盘想像成如下的一个结构,将磁盘盘片想像成线性空间(可以理解为一个数组)。如下图所示,我们可以这样理解对应的结构:

        于是经过上述的操作我们将对于磁盘的管理就变成了对线性空间的管理!接下来,我们先理解一个概念:

        CHS-CHS指的是Cylinder(柱面)、Head(磁头)、Sector(扇区)。这是一种磁盘寻址方式,获取这些CHS信息,通过这些信息就可以对磁盘的信息进行定位。

        理解了CHS后,那我们的OS中是直接使用CHS来进行对应的管理吗?答案为否,OS是软件,磁盘是硬件,硬件定位一个地址,用的是CHS,但是如果OS直接用了这个地址,此时硬件发生改变,OS也要发生变化,所以OS要和硬件做好解耦工作。这就需要Logical Block Address - LBA。

        我们可以在操作系统中以一个一定的数据结构(可以想像成数组)来对磁盘进行管理。这个时候,对于磁盘的管理就变成了对数组的管理!

        需要注意的是:操作系统可以按照扇区为单位进行存储也可以基于文件系统,按照文件块为单位进行数据存取(一般为4KB),这样效率会比较高—即内存到磁盘,磁盘到内存的IO交互。

        对于LBA—CHS的转化:

        我们可以定义一系列的规则来对于磁盘进行管理,比如:数组下标1-100000为第一面,100001-200000为第二面,第一面中1-10000为第一个磁道,1-1000为第一个扇区等等。

理解文件系统

        理解了上述的相关知识点后,我们知道了对于磁盘的管理实际上就是对于OS中“数组”的管理。而为了方便管理,我们可以通过分治的思想将数组再进行分区,这个也可以理解成我们windows中的分盘,你的SSD只有一块,但是分出来了两个盘。如下C和D盘:

        对于管理整个磁盘太困难,就如上图,我们管理512G太难,那么就分多几个区来管理,你可以分100G、150G等等。最后,我们可以用管理小区域的经验进行复制,从而管理整体。

        虽然,我们将磁盘进行了分区,但是分区完后仍然很大,这个时候我们可以进一步划分,这个进一步划分叫做—分组。我们可以将每个分区划分为2GB大小的组,通过对每个组进行管理,在将管理的经验进行复制,从而管理整体。如下:

        Linux ext2文件系统,上图为磁盘文件系统图(内核内存映像肯定有所不同),磁盘是典型的块设备,硬盘分区被划分为一个个的block。一个block的大小是由格式化的时候确定的,并且不可以更改。例如mke2fs的-b选项可以设定block大小为1024、2048或4096字节。而上图中启动块(Boot Block)的大小是确定的,。

        Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。政府管理各区的例子

        超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了

        GDT,Group Descriptor Table:块组描述符,描述块组属性信息,有兴趣的同学可以在了解一下块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用

        inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。

        i节点表:存放文件属性 如 文件大小,所有者,最近修改时间等

        数据区:存放文件内容

        需要注意的是:在文件系统中,文件信息=内容+属性。他们都是数据,内容和属性是分开存储的,但是需要让管理数据写入到块组当中。

inode

ls -li//显示出具体的信息,包含inode编号

        一般情况,一个文件一个inode编号,基本上,每个文件都要有inode。在整个分区具有唯一性,Linux内核中,识别文件和文件名是无关的,只和inode有关。

什么是inode?

        在Linux系统中,inode是一种数据结构,大小通常为128B。它的主要功能是用于描述和定位文件系统中的文件和目录。每个文件或目录都由一个或多个inode组成,这些inode包含了文件或目录的所有信息,如文件大小、创建时间、修改时间、权限等。可以这样理解:

struct inode{
	int ref_count;//引用计数
    大小、权限、所有者、所属组、ACM时间、inode编号等
    int blocks[N]
}

inode Table

        inode表里面会存储很多的inode。每一个inode的大小是固定的,也就是128B,那么我们可以通过inode编号对固定大小的偏移量进行偏移就可找到对应的inode。你可以理解为:通常每一个分组都会有一个起始inode编号,当要计算inode编号时,通过偏移量加上起始inode编号就可得出。那如果我们想知道定位对应的分组位置,也可通过减去起始inode编号来定位。

inode Bitmap

        inode bitmap是一种数据结构,它的主要功能是用于追踪inode table在Linux系统中,inode bitmap是一种数据结构,它的主要功能是用于追踪inode table中的每个inode是否已经被使用。具体来说,每个bitmap中的每一个位都对应于inode table中的一个inode,如果该位为0,则表示对应的inode为空,如果为1,则表示相应的inode entry已被使用。

        这种位图技术(bitmap)的优势在于,当需要修改文件系统时,可以快速找到空闲的inode位置。例如,当需要新建一个文件时,系统会先检查inode bitmap中哪些inode是空闲的,然后将新文件的信息存储到这个空闲的inode中。同样地,当文件被删除时,对应的inode会被标记为可用,以供后续的新建文件使用。

Data blocks

        在Linux系统中,数据区块(block)是文件存储的最小单位,每个由多个连续性的扇区(sector)组成,每个扇区通常是512字节。而一个数据块最常见的大小则是4KB,即连续8个sector组成,用于存储文件数据和目录数据

        需要注意的是:上面提到的inode中会维护一个blocks数组,这个数组记录的是对应数据区块的块号,需要读取文件就可根据这些块号来读取!这个数组大小大概为15,,其中0-12位为直接映射,13:为间接映射,14为三级映射。

        看到这里,你应该就明白了,只要我们知道了inode编号我们就可以根据inode编号找到对应的分组,再通过分组找到对应的inode数据结构,然后通过inode里面的blocks数组来进一步找到对应的数据区块读取对应的数据。

Block Bitmap

        block bitmap是一种数据结构,它的主要功能是用于追踪每个block group中哪些block已经被使用。具体来说,block bitmap是一个特殊的文件,其大小恰好为一个block,而在这个block中,每个bit表示一个对应block的占用情况。如果该位为0,则表示对应的block为空,如果为1,则表示相应的block中存有数据。

        这种block bitmap技术的优势在于,当需要读取或修改文件时,可以快速找到空闲的block位置。例如,当执行写入操作时,系统会首先检查block bitmap,找出哪些block是空闲的,然后将新的数据写入到这些空闲的block中。同样地,当某个block不再使用时,系统会在block bitmap中将相应的bit标记为可用,以供后续的存储操作使用。

        此外,需要注意的是,一个block group中最多只能包含8×4096=32768个block。因此,对于一个含有大量数据的磁盘分区来说,可能需要多个block bitmap来分别记录各个block group的使用情况。

        看到这里你也应该明白了,新建、删除文件只需要改位图即可!

Super Block

        在Linux操作系统中,superblock是一个特殊的数据结构,它记录了文件系统的整体信息,包括inode和block的总量、使用量、剩余量,以及档案系统的格式与相关信息等。具体来说,它包含了文件系统的类型、block大小、block总数、inode大小、inode总数、group的总数等等。此外,每个Group 中的SuperBlock都是对 Main SuperBlock(主SuperBlock)的备份,用于处理主SuperBlock故障或者误删的情况。

        为了保证数据的安全性,Linux会周期性地将所有“脏”的超级块写回磁盘,以减少数据丢失的风险。这种与超级块关联的操作是由数据结构super_operations来描述的,该结构的起始地址存放在超级块的s_op域中。

        需要注意的是:只有个别组内会有SuperBlock,并不是所有的组都有。

        总的来说,superblock是Linux文件系统中非常重要的一部分,它记录了文件系统的关键信息,并负责管理文件系统的运行。通过superblock,我们可以了解到文件系统的详细信息,包括其类型、大小、使用情况等等。同时,它也承担着保障数据安全的重要任务。

GDT

        在Linux操作系统中,GDT(Global Descriptor Table)是一种全局描述符表,主要用于管理和定位内存地址空间。在实模式下,当我们需要对一个内存地址进行访问时,我们使用的是【段基地址:偏移地址】的形式来计算内存的实际地址。然而,当系统进入到保护模式后,内存管理被分为段式和段页式,这时就需要使用到GDT。

        GDT可以看作是一个描述符数组,其中的每个元素都被称为一个选择子。选择子的主要作用是确定段描述符,其目的一方面是为了实现特权级、界限等安全考虑,另一方面则是为了确定段的基地址。具体来说,GDT中的每一项都是由8字节组成,其中包括了段限、基址等关键信息。

        总的来说,GDT是Linux操作系统用来进行内存管理和保护的一种重要数据结构。它通过有效地划分和管理内存地址空间,为运行在操作系统上的各种程序提供了必要的资源和安全保障。

Boot Block

        在Linux中,引导块(Boot Block)是每个磁盘分区的开头部分,它预留了1024字节的大小来存放引导程序和数据。这个区域被称为引导扇区,可能位于第一个Block,即Block 0中,但并不一定会占满这个Block,因为Block的大小可能会大于1024字节。

        引导块中主要包含了启动时所需的基本信息,如启动加载程序和内核。这些信息对于系统的启动过程至关重要。例如,启动加载程序可以负责加载更多的系统组件,而内核则是计算机硬件和系统软件之间的桥梁,用于控制应用程序对硬件的访问。

        值得注意的是,与BIOS中的引导块不同,Linux的引导块不依赖于特定的操作系统或硬件。这是因为Linux是一种开源操作系统,其设计允许在各种不同的硬件和操作系统上运行。因此,无论您使用的是哪种Linux发行版或计算机硬件,引导块的功能和结构基本相同。

对于目录的理解

        目录实际上也是文件,目录的数据块保存的是目录下的文件的文件名和inode的映射关系。通常我们访问一个文件,打开目录,根据文件名,找到inode就可以访问那个文件了。因此,同一个目录下也是不能存在同名文件的!但是我们可以用不同的文件名指向相同的inode。这个可以理解为指针和地址的关系!那这个现象怎么看到呢?这就要说到硬链接和软链接了。

硬链接和软链接

        硬链接和软链接是Linux系统中两种不同类型的文件链接。它们的主要作用是解决文件的共享使用问题。

        硬链接(hard link)是指多个文件名指向同一个inode节点,即同一个文件的数据块。它的特点是:

  • 不允许给文件指定不同的路径;
  • 不能跨分区;
  • 删除一个硬链接并不影响其他硬链接和原文件,只有当最后一个硬链接被删除后,原文件才会被删除。

        软链接(又称符号链接,即 soft link 或 symbolic link)是指一个文件名指向另一个文件的路径。它的特点是:

  • 可以给文件指定不同的路径;
  • 可以跨分区;
  • 删除软链接并不影响原文件,但删除原文件后,软链接将失效。

硬链接
ln 目标文件 硬链接文件名

        可以看到进行硬链接后,链接数由1变为了2,而他们的inode编号是一样的,这就是说明两个文件指向的是同一个文件。当你将其中一个文件删除后,会发现连接数又变回了1。

        根据上面inode的数据结构我们可知,其中有一个引用计数的变量,只要有新的指向就会++,指向减少就会--,当没有指向了才会真正的删除。

硬链接的应用

        通过上图我们可知,当我们创建的是普通的文件时,默认的链接数为1,而我们创建了一个目录后,默认居然是2,这是为什么呢?请看下图:

        表示为本级目录,而 .. 表示为上级目录。. 和 .. 实际上就是硬链接!

软连接
ln -s 目标文件 软链接文件名

        需要注意的是:如下图,和硬链接不同,软链接指向的inode编号是不同的。那这个的作用又是干什么的呢?你可以理解为Windows的快捷方式,对于他的删除不会影响原来的文件。


                         感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

                                       

                                                                        给个三连再走嘛~  

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

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

相关文章

宋仕强论道之华强北的领军企业(四十六)

华强北曾经的3发展是因为领军企业的带动而蓬勃发展,当年的华强集团、赛格集团、桑达集团和华发集团等是其中的代表,但现在他们失去了曾经的带头大哥的地位。其他的例子,如腾讯对于深圳市南山区科技园的带动,华为对龙岗坂田雪象岗头…

MySQL面试题 | 16.精选MySQL面试题

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

Leetcode2207. 字符串中最多数目的子字符串

Every day a Leetcode 题目来源:2207. 字符串中最多数目的子字符串 解法1:贪心 一次遍历 设 pattern 的第一个字符为 x,第二个字符为 y。 根据题意,x 插入的位置越靠左,答案的个数越多;y 插入的位置越…

C#: form 窗体的各种操作

说明:记录 C# form 窗体的各种操作 1. C# form 窗体居中显示 // 获取屏幕的宽度和高度 int screenWidth Screen.PrimaryScreen.Bounds.Width; int screenHeight Screen.PrimaryScreen.Bounds.Height;// 设置窗体的位置 this.StartPosition FormStartPosition.M…

【Android】自定义View onDraw()方法会调用两次

问题 自定义了View后,在构造函数中设置画笔颜色,发现它没起效,但是在onDraw()里设置颜色就会起效,出问题的代码如下: public RoundSeekbarView(Context context, Nullable AttributeSet attrs) {super(context, attrs…

Discuz论坛网站登录账号操作慢,必须强制刷新才会显示登录怎么办?

飞飞发现在登录服务器大本营账号时,输入账号密码登录后还是显示的登录框,强制刷新后才知道已经登录了,每次都要刷新才能正常显示,非常影响用户体验,于是在网上找了类似的问题故障解决方法,目前问题已经解决…

vue安装组件报错In most cases you are behind a proxy or have bad network settings.

解决办法 步骤1 npm config get proxy npm config get https-proxy 如果2个返回值不为null,请执行下面代码,重置为null。否则,直接执行步骤2。 npm config set proxy null npm config set https-proxy null 步骤2 npm config set regis…

MSVS C# Matlab的混合编程系列2 - 构建一个复杂(含多个M文件)的动态库:

前言: 本节我们尝试将一个有很多函数和文件的Matlab算法文件集成到C#的项目里面。 本文缩语: MT = Matlab 问题提出: 1 我们有一个比较复杂的Matlab文件: 这个MATLAB的算法,写了很多的算法函数在其他的M文件里面,这样,前面博客的方法就不够用了。会报错: 解决办法如下…

ceph数据分布式存储

单机存储的问题 存储处理能力不足 传统的IDE的IO值是100次/秒,SATA固态磁盘500次/秒,固态硬盘达到2000-4000次/秒。即使磁盘的IO能力再大数十倍,也不够抗住网站访问高峰期数十万、数百万甚至上亿用户的同时访问,这同时还要受到主机…

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(10)-Fiddler如何设置捕获Firefox浏览器的Https会话

1.简介 经过上一篇对Fiddler的配置后,绝大多数的Https的会话,我们可以成功捕获抓取到,但是有些版本的Firefox浏览器仍然是捕获不到其的Https会话,需要我们更进一步的配置才能捕获到会话进行抓包。 2.宏哥环境 1.宏哥的环境是Wi…

[NSSRound#16 Basic]RCE但是没有完全RCE

题目代码&#xff1a; <?php error_reporting(0); highlight_file(__file__); include(level2.php); if (isset($_GET[md5_1]) && isset($_GET[md5_2])) {if ((string)$_GET[md5_1] ! (string)$_GET[md5_2] && md5($_GET[md5_1]) md5($_GET[md5_2])) {i…

山西电力市场日前价格预测【2024-01-20】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-01-20&#xff09;山西电力市场全天平均日前电价为304.16元/MWh。其中&#xff0c;最高日前电价为486.22元/MWh&#xff0c;预计出现在18:15。最低日前电价为87.43元/MWh&#xff0c;预计出…

Docker容器添加映射端口

方式一 简单粗暴&#xff08;需要等一段时间&#xff09; 直接给现在容器停了&#xff08;当然你要不想停也可以&#xff0c;只是打包会慢一点&#xff0c;当然我是没出意外&#xff0c;如果你怕出现特殊情况&#xff0c;那就先把容器停了&#xff09;&#xff0c;然后把这个容…

Java-初识正则表达式 以及 练习

目录 什么是正则表达式&#xff1f; 1. 正则表达式---字符类&#xff08;一个大括号匹配一个字符&#xff09;&#xff1a; 2. 正则表达式---预字符类&#xff08;也是匹配一个字符&#xff09;&#xff1a; 正则表达式---数量词 &#xff08;可以匹配多个字符&#xff09;…

HarmonyOS-$$语法:内置组件双向同步

$$语法&#xff1a;内置组件双向同步 $$运算符为系统内置组件提供TS变量的引用&#xff0c;使得TS变量和系统内置组件的内部状态保持同步。 内部状态具体指什么取决于组件。例如&#xff0c;Refresh组件的refreshing参数。 使用规则 当前$$支持基础类型变量&#xff0c;以及…

版权申请介绍

因工作需要&#xff0c;做的APP里面涉及卡通人物形象涉及版权问题&#xff0c;这里记录下涉及版权相关知识。 软件本身申请软著&#xff0c;软著即软件著作权&#xff0c;是指软件的开发者或者其他权利人依据有关著作权法律的规定&#xff0c;对于软件作品所享有的发表权、开发…

C++进阶(五)二叉搜索树

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、二叉搜索树概念二、二叉搜索树操作三、二叉搜索树的实现四、二叉搜索树的应用五、二叉搜索…

C++中特殊类的设计与单例模式的简易实现

设计一个只能在堆上创建对象的类 对于这种特殊类的设计我们一般都是优先考虑私有构造函数。然后对于一些特殊要求就直接通过静态成员函数的实现来完成。 class A//构造函数私有&#xff08;也可以析构函数私有&#xff09; { public:static A* creat(){return new A;} privat…

VsCode + CMake构建项目 C/C++连接Mysql数据库 | 数据库增删改查C++封装 | 信息管理系统通用代码 ---- 课程笔记

这个是B站Up主&#xff1a;程序员程子青的视频 C封装Mysql增删改查操作_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1m24y1a79o/?p6&spm_id_frompageDriver&vd_sourcea934d7fc6f47698a29dac90a922ba5a3安装mysql:mysql 下载和安装和修改MYSQL8.0 数据库存储…

2023 年,我患上了 AI 焦虑症!

【作者有话说】2023 年对我来说是神奇的一年&#xff0c;我意外地从一个程序员变成了一个 AI 资讯届的“网红”&#xff0c;到年底时我在 X 平台的阅读量超过 1 亿&#xff0c;微博上的阅读量则超过 10 亿&#xff0c;很多人通过我的微博或者 X 了解最新的 AI 资讯、教程和 Pro…