【Linux】C文件系统详解(四)——磁盘的物理和抽象结构
文章目录
- 磁盘结构
- 磁盘物理结构
- 磁盘的具体物理结构
- 磁盘结构的逻辑抽象
- 文件系统
- BootBlock
- SuperBlock
- GroupDescriptorTable
- inode table
- DataBlocks
- inodeBitmap
- blockBitmap
- linux中的inode 和文件名
- 如何理解文件的增删查改
- 删
- 补充细节
- 1.如果文件误删了,我们该怎么办?
- 2.inode确定分组,inode number是在一个分区内有效,不能跨分区
- 3.上面我们学到的分区,分组,填写系统属性->谁做的呢?什么时候做的呢
- 4.我们如果inode只是单单地用数组和datablock的映射关系
- 5.有没有可能一个分区,数据块没用完,inode没了,或者inode没用完,datablock用完了
磁盘结构
磁盘物理结构
磁盘是计算机上唯一的一个机械设备,同时还是外设->非常慢(相对于cpu/内存)
磁头和盘面是没有挨着的,但是距离依旧很近:好比波音747距离地面一米飞行
对数据做写入和读取:更改基本元素的南北磁极
向磁盘写入:N->S
删除磁盘数据:S->N
所以一旦摩擦生热,就会消磁,数据就会丢失了
磁盘的具体物理结构
尝试在硬件上,理解数据的一次读和写
磁盘中存储的基本单元:扇区,一般是512字节(4096个比特位),也有4kb字节的
一般磁盘,所有的扇区,都是512字节
半径相同的所有扇区,构成一圈"磁道"(多个面的相同磁道形成一个柱面)
在一面上,如何在硬件上定位一个扇区呢?
首先定位哪一个面:只需要确定用哪一个磁头读取,磁头的编号表示的就是哪一个面
然后:
- 先定位在哪一个磁道->由半径决定
- 再确定在该磁道的哪一个扇区->根据扇区的编号来定位一个扇区
磁头 head->柱面(磁道) cylinder->扇区 sector
CHS定位法
而一个普通文件(属性+数据) ->都是数据(0/1) -> 无非就是占用一个或者多个扇区,来进行自己的数据存储的.
我们既然能够用CHS定位任意一个扇区,我们就肯定能定位多个扇区,从而将文件从硬件角度,进行读取或者写入
磁盘结构的逻辑抽象
根据以上内容,如果OS能够得知任意一个CHS地址,就能访问任意一个扇区
但是OS内部不是直接使用的CHS地址
为什么?
- OS是软件,硬件定位一个地址是用得CHS,但是,如果OS直接用了这个地址,万一硬件变了,OS也要发生变化.OS要和硬件做好
解耦
工作- 即便是扇区,512字节,单位IO的基本数据量也是很小的,硬件是按照512字节处理,OS实际进行IO,基本单位是4KB(可以调整->通过编译linux源代码),因此我们把磁盘叫做
块设备
. 所以OS需要一套新的地址来进行块级别的访问
我们将圆形的磁盘盘面想象为一个线性结构:
可是我们磁盘只认CHS
所以我们需要让LBA和CHS互相转换
通过简单的数学运算就可以做到:
伪代码:
假设两个面,每个面5000个扇区,每个磁道500扇区
LBA:6500
C:6500/1000 = 6 (6号磁道)
H:int n = 6500/5000 = 1 (所以在第二面)
S:6500%1000 = 500(第500扇区)
连续读取8个扇区,我们就能得到块了
OS要管理磁盘,就将磁盘看作一个大数组,所以对磁盘的管理,就变成了对数组的管理
先描述,再组织!!!
文件系统
接下来我们谈的都是一个分区:(分区就类似与win的"分盘: C盘,D盘…")
文件 = 内容 + 属性
最终都要以块的形式,保存在磁盘的某个位置
Linux是将内容和属性分离的
BootBlock
与系统的开机有关
SuperBlock
文件系统的所有属性信息
- 文件系统的类型
- 整个分组的情况
为什么每个分组都可能有SB,而且是统一更新的:
是为了防止SB区域坏掉,如果出现故障,整个分区就不可以被使用了,所以要做好备份
(多副本保证分区安全)
GroupDescriptorTable
GDT -> 组描述符–改组内的详细统计等属性信息
inode table
一般而言,一个文件内部所有属性的集合,我们称之为inode节点(128字节),一个文件,有一个inode
即便是一个分区,内部也会存在大量的inode节点
一个group需要有一个区域来专门保存该group内所有文件的inode节点–>inode table
分组内部可能会存在多个inode,所以需要将inode区分开来,每一个inode都会有自己的inode编号
inode编号也属于对应文件的属性id
DataBlocks
一个文件的内容是变化的,我们是用数据块来进行文件内容的保存的,所以一个有效文件,要保存内容,就需要[1,n]个数据块
如果有多个文件,就需要更多的数据块,DataBlocks
Linux查找一个文件,首先是要根据inode编号,来进行文件查找,包括读取内容
struct inode
{
int number;
//...
int blocks[NUM];//先简单理解,对应的就是该文件对应的数据块的编号
}
所以一个inode对应一个文件,该文件inode属性和该文件blocks内容(数据块->4kb)是有映射关系的
inodeBitmap
inode bitmap的每一个bit表示inode是否空闲可用
4kb(一个块):4096*8 = 32768(比特位)
1表示inode正常工作,0表示inode不正常工作
blockBitmap
block bitmap的每一个bit表示datablock是否空闲可用
ls -il//显示文件的inode编号
linux中的inode 和文件名
linux系统只认inode号,inode属性中文件,并不存在文件名!
文件名是给用户用的
->重新认识目录:
- 目录是文件吗–是
- 目录有inode以及内容吗–有
- 任何一个文件,一定是在一个目录内部,所以目录的内容是什么呢?数据块,目录的数据块里面保存的是该目录下文件名和文件inode编号对应的映射关系,在目录内,文件名和inode互为key值
- 当我们访问一个文件的时候,我们是在特定目录下访问的,基本流程是:
- cat log.txt 先要在当前目录下,找到对应的inode编号
- 一个目录也是一个文件,一定隶属于一个分区,结合inode,在该分区中找到分组,在该分组中inodetable中找到inode
- 通过inode和对应的datablock关系找到对应的数据块,并加载到OS,并显示到显示器
如何理解文件的增删查改
删
常识:删除数据比拷贝数据快多了
做法:
- 根据文件名->inode number
- inode number -> inode属性中的映射关系,设置block bitmap 对应的比特位置0
- inode number 设置inode bitmap 对应的比特位为0
删文件只需要修改位图即可
补充细节
1.如果文件误删了,我们该怎么办?
正确的做法:什么都不要干,使用某种软件找到这个文件的inode编号,首先在分组中对应的inodebitmap对应位置置为1,再查找inode表对应的数据块bitmap置为1,然后查找数据块,就能恢复出来了
2.inode确定分组,inode number是在一个分区内有效,不能跨分区
举个例子,一个分区内,有100个分组,每个分组有100个inode编号,当inode是250号的时候,我们就能推算出他是在第三组的
3.上面我们学到的分区,分组,填写系统属性->谁做的呢?什么时候做的呢
是操作系统做的,是在分区完成之后,后面要让分区能够正常使用,我们要用格式化
格式化的过程,其实是OS向分区写入文件系统的管理属性信息
冷门知识:
大型公司更换磁盘,其中的磁盘不能随意流向市场,必须被销毁
4.我们如果inode只是单单地用数组和datablock的映射关系
假设inode里的数组大小是15*4kb,是不是意味着一个文件内容最多放入60kb呢
struct inode
{
int inode number;
int ref_count;
mode_t mode;
int uid;
int gid;
int size;
data;
//...
block datablock[NUM];
}
5.有没有可能一个分区,数据块没用完,inode没了,或者inode没用完,datablock用完了
有可能
这样确实可能会存在资源浪费,但是没什么大影响