当前位置: 首页 > article >正文

【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距离地面一米飞行

对数据做写入和读取:更改基本元素的南北磁极
![[基础IO 2023-11-17 10.43.58.excalidraw|900]]

![[Pasted image 20230325115202.png]]

向磁盘写入:N->S
删除磁盘数据:S->N
所以一旦摩擦生热,就会消磁,数据就会丢失了

磁盘的具体物理结构

尝试在硬件上,理解数据的一次读和写
![[基础IO 2023-11-17 11.03.04.excalidraw|900]]

磁盘中存储的基本单元:扇区,一般是512字节(4096个比特位),也有4kb字节的
一般磁盘,所有的扇区,都是512字节
半径相同的所有扇区,构成一圈"磁道"(多个面的相同磁道形成一个柱面)
在一面上,如何在硬件上定位一个扇区呢?
首先定位哪一个面:只需要确定用哪一个磁头读取,磁头的编号表示的就是哪一个面
然后:

  1. 先定位在哪一个磁道->由半径决定
  2. 再确定在该磁道的哪一个扇区->根据扇区的编号来定位一个扇区

磁头 head->柱面(磁道) cylinder->扇区 sector
CHS定位法

而一个普通文件(属性+数据) ->都是数据(0/1) -> 无非就是占用一个或者多个扇区,来进行自己的数据存储的.
我们既然能够用CHS定位任意一个扇区,我们就肯定能定位多个扇区,从而将文件从硬件角度,进行读取或者写入

磁盘结构的逻辑抽象

根据以上内容,如果OS能够得知任意一个CHS地址,就能访问任意一个扇区
但是OS内部不是直接使用的CHS地址
为什么?

  1. OS是软件,硬件定位一个地址是用得CHS,但是,如果OS直接用了这个地址,万一硬件变了,OS也要发生变化.OS要和硬件做好解耦工作
  2. 即便是扇区,512字节,单位IO的基本数据量也是很小的,硬件是按照512字节处理,OS实际进行IO,基本单位是4KB(可以调整->通过编译linux源代码),因此我们把磁盘叫做块设备. 所以OS需要一套新的地址来进行块级别的访问

我们将圆形的磁盘盘面想象为一个线性结构:
![[基础IO 2023-11-17 21.12.02.excalidraw|900]]

可是我们磁盘只认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]]

接下来我们谈的都是一个分区:(分区就类似与win的"分盘: C盘,D盘…")
![[Pasted Image 20231117214219_277.png]]

文件 = 内容 + 属性

最终都要以块的形式,保存在磁盘的某个位置
Linux是将内容和属性分离的

BootBlock

与系统的开机有关

SuperBlock

文件系统的所有属性信息

  1. 文件系统的类型
  2. 整个分组的情况
    为什么每个分组都可能有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属性中文件,并不存在文件名!
文件名是给用户用的
->重新认识目录:

  1. 目录是文件吗–是
  2. 目录有inode以及内容吗–有
  3. 任何一个文件,一定是在一个目录内部,所以目录的内容是什么呢?数据块,目录的数据块里面保存的是该目录下文件名和文件inode编号对应的映射关系,在目录内,文件名和inode互为key值
  4. 当我们访问一个文件的时候,我们是在特定目录下访问的,基本流程是:
    1. cat log.txt 先要在当前目录下,找到对应的inode编号
    2. 一个目录也是一个文件,一定隶属于一个分区,结合inode,在该分区中找到分组,在该分组中inodetable中找到inode
    3. 通过inode和对应的datablock关系找到对应的数据块,并加载到OS,并显示到显示器

如何理解文件的增删查改

常识:删除数据比拷贝数据快多了
做法:

  1. 根据文件名->inode number
  2. inode number -> inode属性中的映射关系,设置block bitmap 对应的比特位置0
  3. 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];
}

![[基础IO 2023-03-25 17.15.44.excalidraw|900]]

5.有没有可能一个分区,数据块没用完,inode没了,或者inode没用完,datablock用完了

有可能
这样确实可能会存在资源浪费,但是没什么大影响


http://www.kler.cn/a/134991.html

相关文章:

  • @ComponentScan:Spring Boot中的自动装配大师
  • CSS多列布局:打破传统布局的束缚
  • C++面试基础知识:排序算法 C++实现
  • 【专题】计算机网络之网络层
  • python高效处理大数据:将Excel10万数据分批插入MySQL数据库的实战代码
  • 【计算机网络】【网络层】【习题】
  • Bert浅谈
  • vue使用本地图片设置为默认图
  • 【Django使用】django经验md文档10大模块。第4期:Django数据库增删改查
  • 整形数据和浮点型数据在内存中的存储差别
  • 微服务调用链路追踪
  • 使用Python实现3D曲线拟合
  • Java爬虫的使用案例及简单总结
  • 场景交互与场景漫游-路径漫游(7)
  • 腾讯云轻量数据库性能如何?轻量数据库租用配置价格表
  • JavaScript实现飞机发射子弹详解(内含源码)
  • 超聚变服务器关闭超线程CPU的步骤(完整版)
  • 【开源】基于Vue.js的在线课程教学系统的设计和实现
  • 右键菜单和弹出菜单的区别
  • 基于springboot实现校园在线拍卖系统项目【项目源码】计算机毕业设计
  • 如何在Linux上搭建本地Docker Registry并实现远程连接
  • vscode 推送本地新项目到gitee
  • Linux入门(三)
  • 22. 深度学习 - 自动求导
  • 反射和序列化操作会破坏单例模式
  • redis 介绍1