磁盘是计算机上唯一的一个机械设备,同时还是外设->非常慢(相对于cpu/内存)
磁头和盘面是没有挨着的,但是距离依旧很近:好比波音747距离地面一米飞行
对数据做写入和读取:更改基本元素的南北磁极
![![[Pasted image 20230325115202.png]]](https://1000bd.com/contentImg/2023/11/20/140233877.png)
向磁盘写入:N->S
删除磁盘数据:S->N
所以一旦摩擦生热,就会消磁,数据就会丢失了
尝试在硬件上,理解数据的一次读和写
![![[基础IO 2023-11-17 11.03.04.excalidraw|900]]](https://1000bd.com/contentImg/2023/11/20/140233884.png)
磁盘中存储的基本单元:扇区,一般是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需要一套新的地址来进行块级别的访问
我们将圆形的磁盘盘面想象为一个线性结构:
![![[基础IO 2023-11-17 21.12.02.excalidraw|900]]](https://1000bd.com/contentImg/2023/11/20/140233634.png)
可是我们磁盘只认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要管理磁盘,就将磁盘看作一个大数组,所以对磁盘的管理,就变成了对数组的管理
先描述,再组织!!!
![![[基础IO 2023-11-17 21.40.52.excalidraw|900]]](https://1000bd.com/contentImg/2023/11/20/140233875.png)
接下来我们谈的都是一个分区:(分区就类似与win的"分盘: C盘,D盘…")
![![[Pasted Image 20231117214219_277.png]]](https://1000bd.com/contentImg/2023/11/20/140233603.png)
文件 = 内容 + 属性
最终都要以块的形式,保存在磁盘的某个位置
Linux是将内容和属性分离的
与系统的开机有关
文件系统的所有属性信息
是为了防止SB区域坏掉,如果出现故障,整个分区就不可以被使用了,所以要做好备份
(多副本保证分区安全)
GDT -> 组描述符–改组内的详细统计等属性信息
一般而言,一个文件内部所有属性的集合,我们称之为inode节点(128字节),一个文件,有一个inode
即便是一个分区,内部也会存在大量的inode节点
一个group需要有一个区域来专门保存该group内所有文件的inode节点–>inode table
分组内部可能会存在多个inode,所以需要将inode区分开来,每一个inode都会有自己的inode编号
inode编号也属于对应文件的属性id
一个文件的内容是变化的,我们是用数据块来进行文件内容的保存的,所以一个有效文件,要保存内容,就需要[1,n]个数据块
如果有多个文件,就需要更多的数据块,DataBlocks
Linux查找一个文件,首先是要根据inode编号,来进行文件查找,包括读取内容
struct inode
{
int number;
//...
int blocks[NUM];//先简单理解,对应的就是该文件对应的数据块的编号
}
所以一个inode对应一个文件,该文件inode属性和该文件blocks内容(数据块->4kb)是有映射关系的
inode bitmap的每一个bit表示inode是否空闲可用
4kb(一个块):4096*8 = 32768(比特位)
1表示inode正常工作,0表示inode不正常工作
block bitmap的每一个bit表示datablock是否空闲可用
ls -il//显示文件的inode编号
linux系统只认inode号,inode属性中文件,并不存在文件名!
文件名是给用户用的
->重新认识目录:
常识:删除数据比拷贝数据快多了
做法:
正确的做法:什么都不要干,使用某种软件找到这个文件的inode编号,首先在分组中对应的inodebitmap对应位置置为1,再查找inode表对应的数据块bitmap置为1,然后查找数据块,就能恢复出来了
举个例子,一个分区内,有100个分组,每个分组有100个inode编号,当inode是250号的时候,我们就能推算出他是在第三组的
是操作系统做的,是在分区完成之后,后面要让分区能够正常使用,我们要用格式化
格式化的过程,其实是OS向分区写入文件系统的管理属性信息
冷门知识:
大型公司更换磁盘,其中的磁盘不能随意流向市场,必须被销毁
假设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];
}
![![[基础IO 2023-03-25 17.15.44.excalidraw|900]]](https://1000bd.com/contentImg/2023/11/20/140233753.png)
有可能
这样确实可能会存在资源浪费,但是没什么大影响