前言
本篇博客我们来看一下文件在磁盘上是怎么存储的,涉及到的文件系统相关知识
💓 个人主页:zkf
⏩ 文章专栏:Linux
若有问题 评论区见📝
🎉欢迎大家点赞👍收藏⭐文章


目录
[1.4CHS && LBA地址](#1.4CHS && LBA地址)
[3.2Block Group](#3.2Block Group)
[3.3 块组内部构成](#3.3 块组内部构成)
[3.3.1 超级块(Super Block)](#3.3.1 超级块(Super Block))
[3.3.2GDT(Group Descriptor Table)](#3.3.2GDT(Group Descriptor Table))
[3.3.3 块位图(Block Bitmap)](#3.3.3 块位图(Block Bitmap))
[3.3.4 inode位图(Inode Bitmap)](#3.3.4 inode位图(Inode Bitmap))
[3.3.5 i节点表(Inode Table)](#3.3.5 i节点表(Inode Table))
[3.3.6 Data Block](#3.3.6 Data Block)
[4.3 软硬连接对比](#4.3 软硬连接对比)
[4.4 软硬连接的⽤途](#4.4 软硬连接的⽤途)
1.理解硬件
1.1磁盘基本结构
在认识文件如何存储在磁盘之前,我们先来认识下磁盘基本构造


由图可知,磁盘的构造,简单来说,随着磁头臂快速转动,由磁头快速定位到磁盘上的对应扇区位置。
1.2磁盘存储结构

其实磁盘纵向看是柱状的,盘片有俩面,每个面上有很多个磁道,每个磁道在纵向看,是个柱面,每个磁道上有对应扇区。
扇区:是磁盘存储数据的基本单位,512字节,块设备。
如何定位⼀个扇区呢?
可以先定位磁头(header) ,确定磁头要访问哪⼀个柱⾯(磁道)(cylinder) ,定位⼀个扇区(sector)
以上定位是CHS地址定位
⽂件 = 内容+属性 都是数据,⽆⾮就是占据那⼏个扇区的问题!能定位⼀个扇区了,能不能定位多个扇区呢?
扇区是从磁盘读出和写⼊信息的最⼩单位,通常⼤⼩为 512 字节。
磁头(head)数:每个盘⽚⼀般有上下两⾯,分别对应1个磁头,共2个磁头
磁道(track)数:磁道是从盘⽚外圈往内圈编号0磁道,1磁道...,靠近主轴的同⼼圆⽤于停靠磁
头,不存储数据
柱⾯(cylinder)数:磁道构成柱⾯,数量上等同于磁道个数
扇区(sector)数:每个磁道都被切分成很多扇形区域,每道的扇区数量相同
圆盘(platter)数:就是盘⽚的数量
磁盘容量=磁头数 × 磁道(柱⾯)数 × 每道扇区数 × 每扇区字节数
细节:传动臂上的磁头是共进退的(这点⽐较重要,后⾯会说明)
柱⾯(cylinder),磁头(head),扇区(sector),显然可以定位数据了,这就是数据定位(寻址)⽅式之⼀,CHS寻址⽅式。
CHS寻址
对早期的磁盘⾮常有效,知道⽤哪个磁头,读取哪个柱⾯上的第⼏扇区就可以读到数据了。
但是CHS模式⽀持的硬盘容量有限,因为系统⽤8bit来存储磁头地址,⽤10bit来存储柱⾯地
址,⽤6bit来存储扇区地址,⽽⼀个扇区共有512Byte,这样使⽤CHS寻址⼀块硬盘最⼤容量
为256 * 1024 * 63 * 512B = 8064 MB(1MB = 1048576B)(若按1MB=1000000B来算就是
8.4GB)
1.3磁盘的逻辑结构
那么磁盘本质上虽然是硬质的,但是逻辑上我们可以把磁盘想象成为卷在⼀起的磁带,那么磁盘的逻辑存储结构我们也可以类似于:
这样每⼀个扇区,就有了⼀个线性地址(其实就是数组下标),这种地址叫做 LBA
⼀个细节:传动臂上的磁头是共进退的
柱⾯是⼀个逻辑上的概念,其实就是每⼀⾯上,相同半径的磁道逻辑上构成柱⾯。
所以,磁盘物理上分了很多⾯,但是在我们看来,逻辑上,磁盘整体是由"柱⾯"卷起来的。
整个磁盘所有盘⾯的同⼀个磁道,即柱⾯展开:
整个磁盘不就是多张⼆维的扇区数组表(三维数组?)
所有,寻址⼀个扇区:先找到哪⼀个柱⾯(Cylinder) ,在确定柱⾯内哪⼀个磁道(其实就是磁头位置,Head),在确定扇区(Sector),所以就有了 CHS 。
我们之前学过C/C++的数组,在我们看来,其实全部都是⼀维数组:
所以,每⼀个扇区都有⼀个下标,我们叫做 LBA(Logical Block Address) 地址,其实就是线性
地址。所以怎么计算得到这个LBA地址呢?
LBA地址转成CHS地址,CHS如何转换成为LBA地址。
1.4CHS && LBA地址
CHS转成LBA:
磁头数*每磁道扇区数 = 单个柱⾯的扇区总数
LBA = 柱⾯号C*单个柱⾯的扇区总数 + 磁头号H*每磁道扇区数 + 扇区号S - 1
即:LBA = 柱⾯号C*(磁头数*每磁道扇区数) + 磁头号H*每磁道扇区数 + 扇区号S - 1
扇区号通常是从1开始的,⽽在LBA中,地址是从0开始的
柱⾯和磁道都是从0开始编号的
总柱⾯,磁道个数,扇区总数等信息,在磁盘内部会⾃动维护,上层开机的时候,会获取到这些参
数。
LBA转成CHS:
柱⾯号C = LBA // (磁头数*每磁道扇区数)【就是单个柱⾯的扇区总数】
磁头号H = (LBA % (磁头数*每磁道扇区数)) // 每磁道扇区数
扇区号S = (LBA % 每磁道扇区数) + 1
"//": 表⽰除取整
所以:从此往后,在磁盘使⽤者看来,根本就不关⼼CHS地址,⽽是直接使⽤LBA地址,磁盘内部⾃⼰转换。所以:
从现在开始,磁盘就是⼀个 元素为扇区 的⼀维数组,数组的下标就是每⼀个扇区的LBA地址。OS使⽤磁盘,就可以⽤⼀个数字访问磁盘扇区了。
2.引入文件系统
2.1引入"块"的概念
其实硬盘是典型的"块"设备,操作系统读取硬盘数据的时候,其实是不会⼀个个扇区地读取,这样
效率太低,⽽是⼀次性连续读取多个扇区,即⼀次性读取⼀个"块"(block)。
硬盘的每个分区是被划分为⼀个个的"块"。⼀个"块"的⼤⼩是由格式化的时候确定的,并且不可
以更改,最常⻅的是4KB,即连续⼋个扇区组成⼀个 "块"。"块"是⽂件存取的最⼩单位。
注意:
磁盘就是⼀个三维数组,我们把它看待成为⼀个"⼀维数组",数组下标就是LBA,每个元素都是扇
区
每个扇区都有LBA,那么8个扇区⼀个块,每⼀个块的地址我们也能算出来。
知道LBA:块号 = LBA/8
知道块号:LAB=块号*8 + n. (n是块内第⼏个扇区)
2.2引入"分区"的概念
其实磁盘是可以被分成多个分区(partition)的,以Windows观点来看,你可能会有⼀块磁盘并且将它分区成C,D,E盘。那个C,D,E就是分区。分区从实质上说就是对硬盘的⼀种格式化。但是Linux的设备都是以⽂件形式存在,那是怎么分区的呢?
柱⾯是分区的最⼩单位,我们可以利⽤参考柱⾯号码的⽅式来进⾏分区,其本质就是设置每个区的起
始柱⾯和结束柱⾯号码。 此时我们可以将硬盘上的柱⾯(分区)进⾏平铺,将其想象成⼀个⼤的平⾯,如下图所⽰:
注意:
柱⾯⼤⼩⼀致,扇区个位⼀致,那么其实只要知道每个分区的起始和结束柱⾯号,知道每
⼀个柱⾯多少个扇区,那么该分区多⼤,其实和解释LBA是多少也就清楚了

2.3引⼊"inode"概念
之前我们说过 ⽂件 = 数据 + 属性 ,我们使⽤ ls -l 的时候看到的除了看到⽂件名,还能看到⽂件元
数据(属性)。
root@localhost linux\] # ls -l 总⽤量 12 -rwxr-xr-x. 1 root root 7438 "9 ⽉ 13 14:56" a.out -rw-r--r--. 1 root root 654 "9 ⽉ 13 14:56" test.c 每⾏包含7列: 模式 硬链接数 ⽂件所有者 组 ⼤⼩ 最后修改时间 ⽂件名 ls -l读取存储在磁盘上的⽂件信息,然后显⽰出来 其实这个信息除了通过这种⽅式来读取,还有⼀个stat命令能够看到更多信息 \[root@localhost linux\] # stat test.c File: "test.c" Size: 654 Blocks: 8 IO Block: 4096 普通⽂件 Device: 802 h/ 2050 d Inode: 263715 Links: 1 Access: ( 0644 /-rw-r--r--) Uid: ( 0 / root) Gid: ( 0 / root) Access: 2017-09-13 14 : 56 : 57.059012947 + 0800 Modify: 2017-09-13 14 : 56 : 40.067012944 + 0800 Change: 2017-09-13 14 : 56 : 40.069012948 + 0800 到这我们要思考⼀个问题,⽂件数据都储存在"块"中,那么很显然,我们还必须找到⼀个地⽅储存 ⽂件的元信息(属性信息),⽐如⽂件的创建者、⽂件的创建⽇期、⽂件的⼤⼩等等。这种储存⽂件元信息的区域就叫做inode,中⽂译名为"索引节点"。 每⼀个⽂件都有对应的inode,⾥⾯包含了与该⽂件有关的⼀些信息。为了能解释清楚inode,我们需要是深⼊了解⼀下⽂件系统。 Linux下⽂件的存储是属性和内容分离存储的 Linux下,保存⽂件属性的集合叫做inode,⼀个⽂件,⼀个inode,inode内有⼀个唯⼀ 的标识符,叫做inode号 再次注意: ⽂件名属性并未纳⼊到inode数据结构内部 inode的⼤⼩⼀般是128字节或者256,我们后⾯统⼀128字节 任何⽂件的内容⼤⼩可以不同,但是属性⼤⼩⼀定是相同的 1.到⽬前为⽌,相信⼤家还有两个问题: 我们已经知道硬盘是典型的"块"设备,操作系统读取硬盘数据的时候,读取的基本单位 是"块"。"块"⼜是硬盘的每个分区下的结构,难道"块"是随意的在分区上排布的吗?那要怎 么找到"块"呢? 2.还 有就是上⾯提到的存储⽂件属性的inode,⼜是如何放置的呢? 其实这一切都是⽂件系统组织管理这些的!!
3.Ext2文件系统
3.1宏观认识
所有的准备⼯作都已经做完,是时候认识下⽂件系统了。我们想要在硬盘上储⽂件,必须先把硬盘格式化为某种格式的⽂件系统,才能存储⽂件。⽂件系统的⽬的就是组织和管理硬盘中的⽂件。在
Linux 系统中,最常⻅的是 ext2 系列的⽂件系统。其早期版本为 ext2,后来⼜发展出 ext3 和 ext4。 ext3 和 ext4 虽然对 ext2 进⾏了增强,但是其核⼼设计并没有发⽣变化,我们仍是以较⽼的 ext2 作为演⽰对象。
ext2⽂件系统将整个分区划分成若⼲个同样⼤⼩的块组 (Block Group),如下图所⽰。只要能管理⼀个分区就能管理所有分区,也就能管理所有磁盘⽂件。
上图中启动块(Boot Block/Sector)的⼤⼩是确定的,为1KB,由PC标准规定,⽤来存储磁盘分区信息和启动信息,任何⽂件系统都不能修改启动块。启动块之后才是ext2⽂件系统的开始。
3.2Block Group
ext2⽂件系统会根据分区的⼤⼩划分为数个Block Group。⽽每个Block Group都有着相同的结构组
成。政府管理各区的例⼦
3.3 块组内部构成
3.3.1 超级块(Super Block)
存放⽂件系统本⾝的结构信息,描述整个分区的⽂件系统信息。记录的信息主要有:bolck 和 inode的总量,未使⽤的block和inode的数量,⼀个block和inode的⼤⼩,最近⼀次挂载的时间,最近⼀次写⼊数据的时间,最近⼀次检验磁盘的时间等其他⽂件系统的相关信息。Super Block的信息被破坏,可以说整个⽂件系统结构就被破坏了
超级块在每个块组的开头都有⼀份拷⻉(第⼀个块组必须有,后⾯的块组可以没有)。 为了保证⽂件系统在磁盘部分扇区出现物理问题的情况下还能正常⼯作,就必须保证⽂件系统的super block信息在这种情况下也能正常访问。所以⼀个⽂件系统的super block会在多个block group中进⾏备份, 这些super block区域的数据保持⼀致。
3.3.2GDT(Group Descriptor Table)
块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描述符存储⼀个块组 的描述信息,如在这个块组中从哪⾥开始是inode Table,从哪⾥开始是Data
Blocks,空闲的inode和数据块还有多少个等等。块组描述符在每个块组的开头都有⼀份拷⻉。
3.3.3 块位图(Block Bitmap)
Block Bitmap中记录着Data Block中哪个数据块已经被占⽤,哪个数据块没有被占⽤
3.3.4 inode位图(Inode Bitmap)
每个bit表⽰⼀个inode是否空闲可⽤。
3.3.5 i节点表(Inode Table)
存放⽂件属性 如 ⽂件⼤⼩,所有者,最近修改时间等
当前分组所有Inode属性的集合
inode编号以分区为单位,整体划分,不可跨分区
3.3.6 Data Block
数据区:存放⽂件内容,也就是⼀个⼀个的Block。根据不同的⽂件类型有以下⼏种情况:
对于普通⽂件,⽂件的数据存储在数据块中。
对于⽬录,该⽬录下的所有⽂件名和⽬录名存储在所在⽬录的数据块中,除了⽂件名外,ls -l命令
看到的其它信息保存在该⽂件的inode中。
Block 号按照分区划分,不可跨分区
3.4inode和datablock映射(弱化)
inode内部存在 __le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ ,
EXT2_N_BLOCKS =15,就是⽤来进⾏inode和block映射的
这样⽂件=内容+属性,就都能找到了。
思考:
请解释:知道inode号的情况下,在指定分区,请解释:对⽂件进⾏增、删、查、改是在
做什么?
结论:
分区之后的格式化操作,就是对分区进⾏分组,在每个分组中写⼊SB、GDT、Block
Bitmap、Inode Bitmap等管理信息,这些管理信息统称: ⽂件系统
只要知道⽂件的inode号,就能在指定分区中确定是哪⼀个分组,进⽽在哪⼀个分组确定
是哪⼀个inode
拿到inode⽂件属性和内容就全部都有了
创建⼀个新⽂件主要有以下4个操作:
- 存储属性
内核先找到⼀个空闲的i节点(这⾥是263466)。内核把⽂件信息记录到其中。 - 存储数据
该⽂件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。将内核缓冲区的第⼀块
数据复制到300,下⼀块复制到500,以此类推。 - 记录分配情况
⽂件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。 - 添加⽂件名到⽬录
新的⽂件名abc。linux如何在当前的⽬录中记录这个⽂件?内核将⼊⼝(263466,abc)添加到
⽬录⽂件。⽂件名和inode之间的对应关系将⽂件名和⽂件的内容及属性连接起来。
3.5目录与文件名
问题:
我们访问⽂件,都是⽤的⽂件名,没⽤过inode号啊?
⽬录是⽂件吗?如何理解?
答案:
⽬录也是⽂件,但是磁盘上没有⽬录的概念,只有⽂件属性+⽂件内容的概念。
⽬录的属性不⽤多说,内容保存的是:⽂件名和Inode号的映射关系
所以,访问⽂件,必须打开当前⽬录,根据⽂件名,获得对应的inode号,然后进⾏⽂件访问
所以,访问⽂件必须要知道当前⼯作⽬录,本质是必须能打开当前⼯作⽬录⽂件,查看⽬录⽂件的
内容!
3.6路径分析
问题:打开当前⼯作⽬录⽂件,查看当前⼯作⽬录⽂件的内容?当前⼯作⽬录不也是⽂件吗?我们访问当前⼯作⽬录不也是只知道当前⼯作⽬录的⽂件名吗?要访问它,不也得知道当前⼯作⽬录的inode吗?
答案1:所以也要打开:当前⼯作⽬录的上级⽬录,额....,上级⽬录不也是⽬录吗??不还是上⾯的问题吗?
答案2:所以类似"递归",需要把路径中所有的⽬录全部解析,出⼝是"/"根⽬录。
最终答案3:⽽实际上,任何⽂件,都有路径,访问⽬标⽂件
都要从根⽬录开始,依次打开每⼀个⽬录,根据⽬录名,依次访问每个⽬录下指定的⽬录,直到访问到test.c。这个过程叫做Linux路径解析。
💡 注意:
所以,我们知道了:访问⽂件必须要有⽬录+⽂件名=路径的原因
根⽬录固定⽂件名,inode号,⽆需查找,系统开机之后就必须知道
可是路径谁提供?
你访问⽂件,都是指令/⼯具访问,本质是进程访问,进程有CWD!进程提供路径。
你open⽂件,提供了路径
可是最开始的路径从哪⾥来?
所以Linux为什么要有根⽬录, 根⽬录下为什么要有那么多缺省⽬录?
你为什么要有家⽬录,你⾃⼰可以新建⽬录?
上⾯所有⾏为:本质就是在磁盘⽂件系统中,新建⽬录⽂件。⽽你新建的任何⽂件,都在你或者系
统指定的⽬录下新建,这不就是天然就有路径了嘛!
系统+⽤⼾共同构建Linux路径结构
3.7路径缓存
问题1:Linux磁盘中,存在真正的⽬录吗?
答案:不存在,只有⽂件。只保存⽂件属性+⽂件内容
问题2:访问任何⽂件,都要从/⽬录开始进⾏路径解析?
答案:原则上是,但是这样太慢,所以Linux会缓存历史路径结构
问题2:Linux⽬录的概念,怎么产⽣的?
答案:打开的⽂件是⽬录的话,由OS⾃⼰在内存中进⾏路径维护
Linux中,在内核中维护树状路径结构的内核结构体叫做: struct dentry
注意:
每个⽂件其实都要有对应的dentry结构,包括普通⽂件。这样所有被打开的⽂件,就可以在内存中
形成整个树形结构
整个树形节点也同时会⾪属于LRU(Least Recently Used,最近最少使⽤)结构中,进⾏节点淘汰
整个树形节点也同时会⾪属于Hash,⽅便快速查找
更重要的是,这个树形结构,整体构成了Linux的路径缓存结构,打开访问任何⽂件,都在先在这
棵树下根据路径进⾏查找,找到就返回属性inode和内容,没找到就从磁盘加载路径,添加dentry
结构,缓存新路径
3.8文件系统总结




4.软硬链接
4.1硬链接
我们看到,真正找到磁盘上⽂件的并不是⽂件名,⽽是inode。其实在linux中可以让多个⽂件名对应于同⼀个inode。
root@localhost linux\] # touch abc \[root@localhost linux\] # ln abc def \[root@localhost linux\] # ls -li abc def 263466 abc 263466 def abc和def的链接状态完全相同,他们被称为指向⽂件的硬链接。内核记录了这个连接数,inode 263466 的硬连接数为2。 我们在删除⽂件时⼲了两件事情:1.在⽬录中将对应的记录删除,2.将硬连接数-1,如果为0,则将对应的磁盘释放
4.2软链接
硬链接是通过inode引⽤另外⼀个⽂件,软链接是通过名字引⽤另外⼀个⽂件,但实际上,新的⽂件和被引⽤的⽂件的inode不同,应⽤常⻅上可以想象成⼀个快捷⽅式。在shell中的做法
root@localhost linux\] # ln -s abc.s abc \[root@localhost linux\] # ls -li 263563 -rw-r--r--. 2 root root 0 9 ⽉ 15 17 : 45 abc 261678 lrwxrwxrwx. 1 root root 3 9 ⽉ 15 17 : 53 abc.s -\> abc 263563 -rw-r--r--. 2 root root 0 9 ⽉ 15 17 : 45 def 下⾯解释⼀下⽂件的三个时间: Access 最后访问时间 Modify ⽂件内容最后修改时间 Change 属性最后修改时间
4.3 软硬连接对比
软连接是独⽴⽂件
硬链接只是⽂件名和⽬标⽂件inode的映射关系
4.4 软硬连接的⽤途
硬链接
. 和 .. 就是硬链接
⽂件备份
软连接
类似快捷方式
结束语:
文件系统所有知识总结完毕
感谢观看!!