【Linux庖丁解牛】— 文件系统!

1 引⼊"块"概念

其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会⼀个个扇区地读取,这样 效率太低,⽽是⼀次性连续读取多个扇区,即⼀次性读取⼀个”块”(block)。

硬盘的每个分区是被划分为⼀个个的”块”。⼀个”块”的⼤⼩是由格式化的时候确定的,并且不可 以更改,最常⻅的是4KB,即连续⼋个扇区组成⼀个”块”。”块”是⽂件存取的最⼩单位。

注意:

• 磁盘就是⼀个三维数组,我们把它看待成为⼀个"⼀维数组",数组下标就是LBA,每个元素都是扇 区

• 每个扇区都有LBA,那么8个扇区⼀个块,每⼀个块的地址我们也能算出来。

• 知道LBA:块号=LBA/8

 • 知道块号:LAB=块号*8+n.(n是块内第⼏个扇区)

2 引⼊"分区"概念

其实磁盘是可以被分成多个分区(partition)的,以Windows观点来看,你可能会有⼀块磁盘并且将 它分区成C,D,E盘。那个C,D,E就是分区。分区从实质上说就是对硬盘的⼀种格式化。但是Linux的设备 都是以⽂件形式存在,那是怎么分区的呢?

柱⾯是分区的最⼩单位,我们可以利⽤参考柱⾯号码的⽅式来进⾏分区,其本质就是设置每个区的起 始柱⾯和结束柱⾯号码。此时我们可以将硬盘上的柱⾯(分区)进⾏平铺,将其想象成⼀个⼤的平 ⾯,如下图所⽰:  

3 ext2⽂件系统

3.1 inode Table&Data Blocks

操作系统在给磁盘分区后,由于每个区的大小可能还是很大,为了方便管理,还会进行分组。我们知道文件=内容+属性,在Linux下,内容和属性是分开存储的,内容存储在Data Blocks中【以快4kb进行存储】。在Linux中,正常文件都要有自己的属性集合{文件大小,创建时间,权限,类型等},而这些属性则放在一个叫iNode的结构体【128字节】中

这里有一个特殊情况,文件名不会作为属性,保存在文件的iNode当中!为什么呢?

以我们现在肤浅的理解:inode节点的大小是固定的,而每个文件名大小是不定的,如果让inode保存文件名就会让这个节点处于一个很尴尬的地位。我们也不可能做一个定长的字符数组,太短不行,太长也势必会浪费很多空间。

在一个组中,有一个inode表,所有的inode节点都放在这张表中。内存读取数据是以快为单位,也就是一次读取4kb【一个数据块,会保存32个inode】。那我们访问一个inode时,其他inode是不是也加载到内存当中了呢?雀氏如此,有些inode我们可能不会访问,即使加载到内存当中。不过,这样做也有一定的原因,连在一起的inode一本来说都是一起创建有一定联系的文件。它们有更大的概率会被同时访问,这样它们就不用多次加载了,这也就是局部性原理,和vector扩容有异曲同工之妙。

在inode中没有存储文件名,那我们如何区分一个文件的唯一性呢?

答案就是int inode_number,每个inode都有一个编号来区分文件的唯一性。

我们用ls -li 就可以查看一个文件的inode编号了。

3.2 Block Bitmap&inode Bitmap

我们现在已经知道文件的属性和内容分别存储在inode表和数据块当中,但是,文件系统是如何管理这些区域呢,比如,文件系统是如何知道哪些数据块使用了,哪些没有使用,哪些inode节点使用了,哪些inode节点没有使用呢?

很简单,在一个分组中有两张位图Block Bitmapinode Bitmap,两张位图当中的每个比特位对应的就是每个数据块和节点。如果比特位是0则表示这块区域没有被使用,为1则表示已经被使用。

3.3 GDT(Group Descriptor Table)

块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描 述符存储⼀个块组的描述信息,如在这个块组中从哪⾥开始是inode Table从哪⾥开始是Data Blocks,空闲的inode和数据块还有多少个等等。块组描述符在每个块组的开头都有⼀份拷贝。

// 磁盘级blockgroup的数据结构 
/** Structure of a blocks group descriptor*/
struct ext2_group_desc
{__le32 bg_block_bitmap; /* Blocks bitmap block */__le32 bg_inode_bitmap; /* Inodes bitmap */__le32 bg_inode_table; /* Inodes table block*/__le16 bg_free_blocks_count; /* Free blocks count */__le16 bg_free_inodes_count; /* Free inodes count */__le16 bg_used_dirs_count; /* Directories count */__le16 bg_pad;__le32 bg_reserved[3];
};

3.4 超级块(Super Block)  


存放⽂件系统本⾝的结构信息描述整个分区的⽂件系统信息。记录的信息主要有:bolck 和inode的总量,未使⽤的block和inode的数量,⼀个block和inode的⼤⼩,最近⼀次挂载的时间,最近⼀次写⼊数据的时间,最近⼀次检验磁盘的时间等其他⽂件系统的相关信息。Super Block的信息被破坏,可以说整个⽂件系统结构就被破坏了超级块在每个块组的开头都有⼀份拷⻉(第⼀个块组必须有,后⾯的块组可以没有)。

为了保证⽂件系统在磁盘部分扇区出现物理问题的情况下还能正常⼯作,就必须保证⽂件系统的super block信息在这种情况下也能正常访问。所以⼀个⽂件系统的super block会在block group中进⾏备份,这些super block区域的数据保持⼀致。

3.5 一些细节

> 格式化的本质就是写入文件系统的管理信息。

> Super Block在分区中有多份备份,在某些分组中存在。为什么不在一个分区的开始记录一份,因为超级快实在太重要了,需要多份备份。

> inode和数据块是跨组编号的。【即在一个分区内,所有的inode编号和块号都是唯一的】

> inode和数据块不能跨分区。

> 在Linux中看待目录和文件一样,目录也有自己的inode和数据块。只不过,目录的数据块中存储的内容是该目录下的文件名和该文件inode的映射关系。我们之前说一个文件的文件名不会被看做属性被记录到inode当中,现在我们知道文件名是被记录到该文件所属目录的数据块当中了。但是,这里有一个问题:我们知道可以用一个文件的inode找到文件【也就是说,文件系统只认inode编号】,但是,从我们用户的角度来看,我们是用文件名来找到一个文件的。所以,文件系统是如何通过我们提供的文件名找到文件的呢?

有了上面的铺垫,我们也可以很好理解:当我们要查找一个磁盘文件时,文件系统先打开该文件所在的当前目录【也就是路径】,得到文件名和inode之间的映射关系,最后也是用该文件的inode找到该文件。所以,我们访问任何文件都必须要有路径,找文件的本质是:从根目录开始,进行路径解析,找到对应的文件。

3.6 路径缓存

我们访问任何路径都要从根目录下开始进行路径解析吗?这样不就是一直在做磁盘IO吗,效率是不是太低了??

操作系统在我们进行路径解析的时候,会把历史路径【目录】记录下来,形成一课多叉树【这颗多叉树和PCB一样是内存级别的】,进行保存。这也就是Linux的树状目录结构!

Linux中,在内核中维护树状路径结构的内核结构体叫做: struct dentry

struct dentry {atomic_t d_count;unsigned int d_flags; /* protected by d_lock */spinlock_t d_lock; /* per dentry lock */struct inode *d_inode; /* Where the name belongs to - NULL is* negative *//** The next three fields are touched by __d_lookup. Place them here* so they all fit in a cache line.*/struct hlist_node d_hash; /* lookup hash list */struct dentry *d_parent; /* parent directory */struct qstr d_name;struct list_head d_lru; /* LRU list *//** d_child and d_rcu can share memory*/union {struct list_head d_child; /* child of parent list */struct rcu_head d_rcu;} d_u;struct list_head d_subdirs; /* our children */struct list_head d_alias; /* inode alias list */unsigned long d_time; /* used by d_revalidate */struct dentry_operations *d_op;struct super_block *d_sb; /* The root of the dentry tree */void *d_fsdata; /* fs-specific data */
#ifdef CONFIG_PROFILINGstruct dcookie_struct *d_cookie; /* cookie, if any */
#endifint d_mounted;unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
};

注意:
• 每个⽂件其实都要有对应的dentry结构,包括普通⽂件。这样所有被打开的⽂件,就可以在内存中
形成整个树形结构
• 整个树形节点也同时会⾪属于LRU(Least Recently Used,最近最少使⽤)结构中,进⾏节点淘汰
• 整个树形节点也同时会⾪属于Hash,⽅便快速查找 
• 更重要的是,这个树形结构,整体构成了Linux的路径缓存结构,打开访问任何⽂件,都在先在这
棵树下根据路径进⾏查找,找到就返回属性inode和内容,没找到就从磁盘加载路径,添加dentry
结构,缓存新路径

3.7 挂载分区

我们已经可以通过inode在指定分区中找到文件了,也可以通过目录文件内容找到inode,但是inode不是不能跨分区吗,我们怎么知道这个文件在哪个分区呢?

在Linux中,某个分区是无法直接访问的,这时候就需要将目录挂载到指定分区。也就是说,分区写入文件系统,需要和指定的目录关联,进行挂载才能使用。

如此一来,我们就可以根据访问目标文件的“路径前缀”来准确判断我在哪一个分区

至此,我们也可以更深刻的理解fopen时,操作系统干了什么了:首先拿到当前文件的路径,再根据文件名和inode的映射关系得到inode,拿着inode在磁盘中进行索引找到当前文件,如果有可能,也会在dentry树中索引提高效率。接着系统会在内存中创建struct file对象,将文件的属性信息拷贝到file对象中的inode字段中,将文件的全部内容或部分内容写入文件内核缓冲区当中。同时,系统也会创建对应的文件描述符表,并返回对应的文件描述符!

3.8 文件系统相关总结图表

4. 软硬链接 

4.1 软连接

我们先来看一个现象:

可以看出,软连接是一个独立的文件,因为它有独立的inode number。 

那软连接有什么用呢?

在一些大型工程当中,我们的可执行文件可能被藏在一些比较深的路径,直接找到这个路径可能比较麻烦,这时候,使用软链接我们就可以更方便的执行该程序,如下:

这就相当于Windows当中的快捷键,而软链接文件的内容就是目标文件的路径。当然,软链接还有其他的作用,以后再说。 

4.2 硬链接

我们先来看一个现象:

我们直接使用了命令ln不带选项就是硬链接,我们发现这两个文件的inode编号都是相同的,所以硬链接文件就是不是独立的文件,而是一组新的文件名和inode的映射关系。 

我们再看到这个数字,这个数字其实就是硬链接数。当这个硬链接数为2的时候,说明这个文件有两个,也就是说硬链接可以帮我们完成一个文件的备份,当我们以一个文件名删除文件时,这个文件的内容和属性其实还在,我们通过另一个文件名就可以得到。这也就是硬链接的作用!

上面操作创建了一个目录dir,这个目录的硬链接数为什么是2呢,我们明明没有注定完成硬链接操作,原因就是,在dir目录下的影藏文件【.】就是当前路径【也就是代表dir目录】,所以 . 就是dir目录的硬链接! .. 也是同样的道理啊。

至此,我们也明白了.和..的本质就是硬链接!

但是,在Linux中,我们用户却并不可以对目录进行硬链接!但是,系统当中的.和..不就是目录的硬链接文件吗!这不是只许州官放火,不许百姓点灯吗?事实就是如此,但是为什么系统不让用户自定义硬链接文件,却又自己设计.和..的硬链接文件呢?

如果,我们在树状的目录结构当中,其中一个文件对根目录进行硬链接,那这就容易形成路径换问题。那我们在目录查找文件时就容易出现问题。而对于.和..硬链接文件虽然也形成了路径换,但是由于名字特殊,做特殊处理即可!.和..存在的意义也是为了用户方便进行命令操作。

还有个问题,软链接不也形成路径环了吗,但是我们要看到改文件的类型是被l标识的!做特殊判断即可!所以,在Linux中有些东西有其存在的考量和并不存在的理由。

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

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

相关文章

如何通过自动化减少重复性工作

通过自动化减少重复性工作的关键策略包括:1、识别可被规则化操作的任务、2、引入RPA(机器人流程自动化)工具、3、整合AI与业务流程系统、4、部署脚本与低代码平台、5、持续优化自动化场景与效率。 其中,“引入RPA工具”被广泛认为…

知识变现全链路设计:从IP打造到商业闭环的系统方法论|创客匠人

一、变现低效根源:碎片化努力为何换不来持续增长? 创客匠人服务上千位知识创业者后发现,变现乏力多因缺乏系统设计:某营销专家的课程因定位模糊、表达生硬、渠道单一,低价仍少有人问。文档中提出的“六大超级设计公式…

如何利用人工智能大模型提升流量质量

摘要 流量质量是衡量数字化营销效果的重要指标之一,它反映了用户对网站或应用的兴趣和满意度。流量质量的常用评估方法有点击率、跳出率和用户停留时间等。本文将介绍如何利用人工智能大模型来分析和优化这些指标,提高流量质量,从而提升数字…

从单体架构到微服务:微服务架构演进与实践

一、单体架构的困境与演进 (一)单体应用的初始优势与演进路径 在系统发展的初期,单体架构凭借其简单性和开发效率成为首选。单体应用将整个系统的所有功能模块整合在一个项目中,以单一进程的方式运行,特别适合小型系…

Elasticsearch 自定义排序:使用 Painless 脚本实现复杂排序逻辑

需求背景: 从es查询数据出来的时候,要求type为CATALOG的数据排在最前面,也就是目录类型的要放在最前面,而且要求按照层级排序,从L1到L5顺序排序 直接上解法: {//查询条件"query": {"bool…

华为云Flexus+DeepSeek征文|华为云数字人 + DeepSeek:智能交互的革命性突破

目录 前言 关于华为云数字人和云服务 1、华为云数字人 (1)MetaStudio介绍 (2)应用场景 (3)功能特性 (4)使用体验 2、华为云云服务 华为云数字人结合DeepSeek的核心流程 1、…

【GESP】C++四级练习 luogu-P5729 【深基5.例7】工艺品制作

GESP C四级练习,二维/多维数组练习,难度★★☆☆☆。 题目题解详见:【GESP】C四级练习 luogu-P5729 【深基5.例7】工艺品制作 | OneCoder 【GESP】C四级练习 luogu-P5729 【深基5.例7】工艺品制作 | OneCoderGESP C四级练习,二维…

通过npm install -g yarn安装Yarn显示Proxy代理相关问题如何解决?

手动下载yarn.msi安装包或者yarn.js文件 参考:windows 怎么下载yarn安装包并将下载的yarn文件移动到全局目录并添加执行权限?-CSDN博客

arm交叉编译qt应用中含opengl问题解决

问题是采用正点原子方案中,用虚拟机交叉编译含opengl的qt程序会出现编译失败问题,因为正点原子中的交叉编译qt源码时没有编opengl。 野火似乎有解决: https://doc.embedfire.com/linux/rk356x/Qt/zh/latest/lubancat_qt/install/install_arm…

服务器排查与加固服务详细介绍

一、服务概述 服务器排查与加固服务是针对企业核心信息资产(服务器)的全方位安全保障方案,旨在通过系统性排查潜在风险、修复漏洞、优化配置,提升服务器抗攻击能力,确保业务连续性和数据安全性。该服务覆盖硬件、操作…

提升开发思维的设计模式(下)

上期回顾 提升开发思维的设计模式(上) 2. 设计模式分类(23种设计模式) 2.13 组合模式(Composite Pattern) 将对象组合成树形结构,以表示“整体-部分”的层次结构。 通过对象的多态表现&#…

h5学习笔记:前端打包

这2天做了一个实验。在非module传统的网页,要实现改名和避免缓存。原本这个事情早在几年前就做过借助gulp的方式或者fis3 的工具来完成。然而随着nodejs 来到了24版本后,似乎nodejs的版本这事情就变动复杂多变了。 为什么那么麻烦?实际上开发…

14.OCR字符识别

目录 1. 识别方法 1. OCR识别 2. OCR识别方法1-助手识别 3. OCR识别方法2-算子分割识别 4.文本分割识别 2. 文本分割 1. 借用助手设置参数文本分割+混合识别 2. 借用助手设置参数文本分割场景2 3.不同字符场景 1.倾斜字符 1. 识别方法 1. OCR识别 *OCR *1. 概念 * …

如果将Word里每页的行数设置成50行

https://www.zhihu.com/question/357856175 本文来自知乎林听晴 第一步:新建一个Word文档 打开“页面布局”,之后点击图片圈起来的小图标,即可出现“页面设置”页面。 ​ ​ 路径:页面设置—文档网络,可以看到默认行…

WebRTC(十一):RTCP和SRTCP

RTCP 基本概念 RTCP 是 RTP 的控制协议,用于监控媒体传输质量和参与者状态,并与 RTP 一起工作。RTP 用于传输媒体数据(如音视频),RTCP 则用于传输控制信息。 RTCP 通常和 RTP 同时使用,并通过 不同端口&…

将element-plus table背景改成透明色

方法一:全局修改(推荐) /* 全局透明表格样式 */ .el-table, .el-table__header-wrapper, .el-table__body-wrapper, .el-table__row {background-color: transparent !important; }/* 可选:自定义表头和斑马纹行的透明度 */ .el-table__header th {background-color: rgba(…

安全运营中的漏洞管理和相关KPI

漏洞管理一直是企业网络安全运维中的关键环节,但又是安全运维的痛点。不仅要投入大量的人力物力,还无法被其他运维团队所理解。那么,向领导层和相关团队反映出当前漏洞管理的现状和挑战便是一个急需解决的问题。 通过有效的数据讲好故事,发现问题,或许是做好漏洞管理的突破…

机器学习框架(1)

以吴恩达的《机器学习》课程为蓝本,整理课程框架,自己学习的简单记录。 课程讲解很清楚,建议有空可以看看原课程。 01 单变量线性回归 回归偏向于连续属性,分类偏向于离散属性。 监督学习是给定标签的学习;而无监督学…

AI Ready数据库,OceanBase打了一个样

大数据产业创新服务媒体 ——聚焦数据 改变商业 过去一年,企业对AI的兴趣不减。从接入大模型,到部署RAG(检索增强生成)系统、探索AI Agent,AI从“新技术”变成了“业务工具”的候选项。但一个技术能否真正落地&#x…

趣味数据结构之——链

记得数组吗,一个萝卜一个坑的想象。在数组的世界里我们就是第三视角,置身于坑外的。如果我们是二维平面上的生物,那数组就是一维的线,我们可以随机访问,增删查改,也可以一眼看出数组大小。 那么对于链来说…