引入
之前在Linux------基础IO(1)中我们讲的都是(进程打开的文件)被打开的文件
那些未被打开的文件呢?
大部分的文件都是没有被打开的文件,这些文件在哪保存?磁盘(SSD)
OS要不要管理磁盘上的文件?(如何让OS快速定位一个文件)
要(通过路径快速定位文件)
1.磁盘的了解
1.1机械构成
那个像铁片一样的叫盘片(数据是写在这里面的)
盘片可以理解为一种特殊的光盘,不过光盘是只读的(一旦进行光学拷贝,写一次下次就不能写了) 而盘片可以读取和写入,可以重复写
大部分桌面级磁盘只有一片(两面) 盘片,而企业级的磁盘(云盘)拆开是一摞的
盘片中心是一个高速旋转的马达,旁边有一个磁头(像针一样),关机时磁头会收起
背板(后面的电路板)上面是硬件电路->伺服系统
计算机中的0、1在不同的硬件上的表现不同,在磁盘上,可以把盘片上面存放大量的磁铁,而0、1就对应着磁铁的南、北极
1.2磁盘的物理存储
盘片可以看成无数个 同心圆构成,划分成了一个个区域,这些区域叫磁道(柱面)
磁道中的某一部分称为扇区
扇区(512字节,4KB):是磁盘IO的基本单位(注意:不一定是系统和磁盘IO的基本单位)
磁头、盘面都有唯一的编号,而磁道、扇区也有唯一的编号
如果我想访问磁盘中的一个扇区:
选择磁头==选择盘面
通过磁头定位:磁道/柱面
使用哪个磁头、哪一个扇区 CHS定位法
磁头 -> 磁道 -> 扇区
head cylinder sector
那么任何文件,不就是多个扇区承载的数据吗
为什么磁盘要高速旋转?寻址指定磁道上的扇区
为什么磁头要快速摆动呢?定位磁道/柱面的
上面两个回答都是机械运动(慢)且是外设
1.3磁盘的逻辑存储
磁带见过吧,里面是黑色的带子,这条很长的带子卷起来是圆形的,扯开就是直的带子(线性)
现在抽象一下啊,把磁盘中盘面也(展开)看成这样的线性空间,然后下一个盘面往后接上
假设有一个800G的磁盘
sector array[1677721600]
对磁盘的管理就变成了对数组的增删查改
注意:
不同操作系统IO基本单位可能不同但大部分操作系统都是4KB。
OS认为,一次和磁盘IO一个扇区(512字节)单位太小了,访问效率太慢了,所以操作系统将连续 的8个扇区作为一个基本数据块,即4KB, 所以这4KB就是IO的基本单位
每8个扇区合成一个新的数据块,从而得到一个新的数组
通过数组的下标,该下标被称为LBA(logic block address)也就是逻辑块地址,我们只要知道 每个磁道上的扇区数 和每个盘面上的扇区总数 ,就可以通过计算得到对应的扇区位置
sector / 单盘扇区的个数 = 0->H
sector % 单盘扇区的个数 = temp
temp / 一个磁道上的扇区个数 = 我在哪个磁道 ->C
temp % 一个磁道上的扇区个数 = 结果,我是特定一个磁道的一个扇区->S
线性地址 ->(磁盘自己转化) CHS
4KB / 512字节 = 8
若要访问下标为 1 的地址块写入扇区
1*8 + [0,1,2,3,4,5,6,7] 起始扇区+8个下标的偏移量
下标为2则 2*8 + 偏移量
2.文件系统
2.1认识inode
Linux磁盘文件的特性: 文件 = 内容 + 属性
内容和属性分开存储的
内容的大小不确定,而属性的大小是固定的
因为文件属性的类别都是一样的,只不过不同文件中对应类别存储内容不同
所以设计出了一个结构体用来描述文件属性,该结构体即为inode,大小一般为128字节,每个文件都有自己的inode和对应的inode编号,该inode编号在所处分区内唯一。
所以系统中标识一个文件,用的不是文件名,而是inode编号。
cpp
struct inode
{
//类型
//大小
//权限
//。。。
//inode编号(每个分区唯一)
}
2.2inode table
i节点表:存放文件属性 如:文件大小、所有者、最近修改时间等 inode table
2.3inode 位图
怎么知道哪些inode被使用、哪些没?
inode BitMap(inode 位图):每个bit表示一个inode是否可用
比特位的位置:inode Table中第几个inode
比特位的内容:标识该inode是否被使用
2.4Date block
Date block(数据区):存放文件内容
2.5Block BitMap
Block BitMap(块位图):Block BitMap其中记录着Date block中哪个数据块已经被占用,哪个数据块没被占用
比特位的位置:Date block中第几个数据块
比特位的内容:标识该数据块是否被使用
怎么找到一个文件?
找到一个文件,得找到它的属性和内容,但不是一上来就找inode 、Date block,而是先找到文件在哪个组里
每个组都有起始编号和inode的个数
inode是在分区中唯一的,在组中起始位置和终止位置比较看inode属于哪个组,然后在inode BitMap中找bit确认这个文件是存在的
inode Table里面找到 Date block中的文件内容
起始编号+inode bitmap 中为空的bit(偏移量)
编号 - 偏移量 = 我在inode BitMap 的第几个bitmap
进而能找inode Table -> 进而能找到Date blocks
注意:数据块的大小仅有4KB,但文件可不止,即一个文件可能会占用多个数据块,所以inode结构体中还会有这样的一个设计:
cpp
struct inode
{
//类型
//大小
//权限
//。。。
//inode编号(每个分区唯一)
int block[15];//找多个块中的文件
}
inode表中 block[15]只有15位,只能记15个,每个4KB,难道每个文件最多只能记60KB吗?
其实不然15个下标[0,14]
其中[0,11]是直接映射
[12,13]指向的数据块不直接存数据,而是存后续此文件数据块的编号(这最多也就存8MB)
,二级索引
下标14指向的数据块,里面存到是其它数据块的编号,而其它数据块存的才是后续文件数据块的编号(三级索引)
2.6Group Descriptor Table
Group Descriptor Table(GDT):对一个块组进行管理的数据结构,统计了这个分组的使用情况
2.7Super Block
Super Block:用来管理整个分区,会在Block group 0中存在,还会在零星的Block group(为防止防止文件系统结构被破坏无处覆盖)
分盘(D、E、F等)格式化:向指定分区,写入文件系统
2.8文件名
在Linux中我们一直没有用inode,访问文件用的是文件名
目录是不是文件?是,inode+目录内容
目录内容是啥?文件名:inode编号的映射关系
既然目录也是文件,那么目录也有自己的inode,打开这个目录之前也要找到此目录的inode,这样一直往前找,找到找到根目录(根目录的inode是确定的)
如果目录没有r、w、x权限,无'w'就没法向文件写入所要创建文件的文件名与inode编号的映射关系,自然也就无法创建文件
OS也要对目录做管理 struct dentry
文件的增删查改,对一个文件进行增删查改,都和文件所处的目录有关系
查找一个文件,在内核中,都要逆向的递归般得到 / ,从根目录进行路径解析
inode只在分区内有效,那么上面的内容就有一个大前提,我所要的文件究竟在哪个分区?
一个被写入文件系统的分区,要被Linux使用,必须要先把这个具有文件系统的分区进行**"挂载"**
既然有多个分区,每个分区都有文件系统,OS自然要对文件系统做管理(先描述,再组织)
挂载:将一个文件系统所对应的分区,挂载在对应的目录中
df -h可以查看分区挂载到哪个目录中 mount命令挂载分区到指定目录中
分区的访问都是通过所挂载的路径访问的
OS对文件系统 和目录 都做管理,文件系统和目录都有对应的数据结构
挂载的本质就是让这两种数据结构产生关系
前缀路径根分区挂载的路径进行匹配就能得出此文件是哪个分区的
3.软硬链接
3.1软链接
观察现象
我们可以通过命令:ln -s 文件名 软链接名 创建软链接
link.soft -> test.txt link.soft本质是文件(有inode)
软链接本质就是一个独立的文件,内容存放的是目标文件所在的路径信息,类似于windows系统的 快捷方式
3.2硬链接
也可以用ln 创建硬链接
硬链接本质不是一个独立的文件,其inode与链接的文件相同
若把链接文件删了,硬链接还存在,还能访问链接文件的内容
优点像重命名,硬链接其实是新的文件名和目标文件inode的映射关系
硬链接本质就是在指定的目录下,插入新的文件名和目标文件的映射关系,并让inode的引用计数++