您好,欢迎来到刀刀网。
搜索
您的当前位置:首页【Linux基础IO】文件系统

【Linux基础IO】文件系统

来源:刀刀网


前言

        在文件系统中,并不是所有的文件都会被打开,文件打开后的管理已经做了解释,那没有打开的文件呢 ? 本文就来聊一聊文件系统,磁盘中文件的管理;

在实际情况中,大部分的文件都是不被打开的(当前不需要被访问),都在磁盘中进行保存;

对于这些没有被(进程)打开的文件,也需要进行管理;那么核心工作是什么? 快速定位文件,通过路径快速定位

对于文件系统,需要做的管理工作:

 本质就是文件存储的问题

 1. 文件在磁盘中的管理

1.1 磁盘结构

文件 = 内容 +属性;文件在磁盘中进行存储,必须要方便OS/用户的增删查改;

磁盘硬件 物理存储结构
磁盘的体积较大,在日常使用的手机、笔记本电脑等电子设备一般不会使用;主要用于服务器存储数据;在一些机房的服务器上插的就有磁盘;

        磁盘中的盘面可以进行旋转,通常是以一个固定的转速来旋转。而磁头则可以在盘面上活动,其运动方向主要是垂直于盘面,这样可以在盘面上读取或写入数据。硬盘驱动器通过控制盘面的旋转速度和磁头的移动来实现数据的存储和读取;

磁盘结构图:

 一个磁盘中可以有多个盘面,每个盘面上都可以存储数据,如上有3个盘,6面;

 盘面结构:

 每个盘面中又会有很多的磁道(同心环),每个磁道又会被分成多个扇区,扇区是最小的数据存储单位;(由内到外扇区大小不同,但存储大小是相同的);扇区的大小通常是512字节或4KB;

如果想要向扇区写入数据,磁头应该如何寻址,定位?

CHS定位法:

  • 选择哪一面?——本质就是选择磁头
  • 选择面上哪一个磁道?——磁头活动来跟踪磁道
  • 选择磁道上哪个扇区?——盘面旋转定位扇区

 通过控制磁头的位置来读取或写入数据;

1.2 扇区管理

磁盘分为多个扇区为基本存储单元,对磁盘上的扇区空间也需要进行管理; 

 可以理解为是一个Sector s[n]数组(Sector扇区);

 1~100000第一面、100001~200000 第二面  ...;

1~10000 第一个磁道、10001~20000第二个磁道 ...;

对磁盘的管理就变成了对数组的管理:

  • x/100000->面
  • x/10000 ->磁道
  • x/1000->扇区

 操作系统,可以按照扇区为单位进行存取,也可以基于文件系统,按照文件块为单位进行数据存取;

上述是以磁盘视角,接下来上升到文件系统视角;

LBA到CHS定位的转变,如上述的计算方法,可以进行转化;

 最终对存储设备的管理(OS层面),转换成了对数组的增删查改;

2. 文件系统

2.1 磁盘分区

        假如有500G的硬盘,对于操作系统来说,管理磁盘中的文件,就是对磁盘这500G空间进行管理;

        操作系统如果按照文件块来进行管理,磁盘空间相对于文件块来说太大了,那要如何管理磁盘文件?——分治 对磁盘进行分区;

 访问文件时,最开始我们如何判断文件在哪个分区(也就是常见的分盘:C盘 D盘)?

每个文件都有路径,可以通过路径前缀判断出在哪个分区

2.2 分组管理

 比如把500G分成5个100G的分区,分区又可以划分为组进行管理;

下面是分组的基础结构:

 第一个分区中会有一个Boot Block它是一个启动块(在计算机开机时引导操作系统加载到内存中)

 每个组开始都会记录一个startinode_number方便定位哪个组

块组中除了存储文件,还有很多文件管理的数据;文件管理的数据,比如:
块用了多少,还剩多少,文件的内容和属性存储
信息

文件信息:

  1. 内容
  2. 属性

他们都是数据,在存储时是分开存储的;在使用前,需要先把管理数据写入到块组当中;

整个分区的块组都需要先写入文件管理的数据,这个操作也叫格式化;
所以在电脑中的格式化操作,本质并不是将所有数据清空,只是将用户的文件数据清空,而文件管理数据会重新写入;

2.3 块组结构

 inode表

 注意这里是inode表,inode保存的是文件的属性;

 inode table中不止一个inode结构体,假设inode表的大小是4KB*1000(约为4MB) 约32000个inode;

指令查看incode编号:

一般情况下,一个文件一个inode编号,基本上每个文件都有,在整个分区具有唯一性
在Linux内核中,识别文件,和文件名无关,只和inode编号有关;

块组数据区

         数据区会被分成多个4KB大小的数据块,这里存储的是所有文件的内容数据,数据区的每个数据块都有自己的偏移量/编号;

inode存储文件属性,数据区存储文件内容,那如何通过inode找到对应的文件内容?

 在inode中会存在一个数组(block[n]),数组中存储的就是数据块的编号;比如:block[N]中存储的是1、4、7;那文件对应的文件内容就是1、4、7编号的数据块;

 inode 位图

 inode位图(inode Bitmap):每个bit表示一个inode表中对应位置是否空闲可用;

通过位图可以快速知道inode table的使用情况;

块位图

 Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用;

比特位的位置表示block编号,比特位内容(0/1)对应block是否被使用

 主要结构基本已经介绍完毕,如果新建一个文件并写入hello world,它的具体流程是什么?

  1.  先在inode Bitmap中寻找最近一个没有使用的inode,并把对应的bit位置为1;
  2. 通过inode Bitmap中的bit位偏移量,找到inode table中inode的位置;
  3. 把文件属性写入到 inode 中;(大小、权限、拥有者、所属组、ACM时间、inode编号等);
  4. 寻找数据块存储,通过Block Bitmap快速定位未使用的数据块,并把对应的bit位置为1;
  5. 记录Block Bitmap中偏移量(块号),写入到inode 的block[N]数组中;
  6. 通过inode中的block中记录的块号,将数据写入/刷新到对应的数据块中;

 那删除操作呢?

 删文件只需要改位图即可,删除并不是把所有数据都清空,只是修改位图,令inode、block失效;

 被删除的文件恢复思路:

        删除文件就是把对应的位图置为0,那恢复文件只需知道inode编号即可,误删文件之后,最好不要新建文件,尽可能的不让其他新建的文件数据覆盖原有的数据;可以通过inode编号找到对应的inode Bitmap进行恢复;通过编号找到inode;通过inode中block数组定位到数据块,然后将Blockbitmap进行恢复;此时文件就被恢复了;

GDT

GDT,Group DescriptorTable:块组描述符,描述块组属性信息,它记录的是整个块组的管理信息;比如:整个块组大小、整个块Datablock使用的使用情况、起始块号、下次使用inode的编号;

每个块组都会有这5个属性:GDT、数据区、inode位图、块位图、inode表;

超级块

超级块(Super Block):存放文件系统本身的结构信息;记录的信息主要有:bolck和inode的总量;

        未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了;

super block并不是所有的块组都有,只有个别,少部分的块组有;它存放的是整个分区的管理数据,整个分区的inode和biloc数量以及使用情况;

为什么只要个别部分块组有,为什么不能和Boot Block一样在整个块开始位置?

         为了防止super block出问题,如果super block出问题就会导致整个文件系统被破坏,所以为了防止这种情况,他就会多复制几份,放在不同的块组中,如果出问题,就拷贝其他块组中superblock数据;

每次操作系统启动时,就会把每个分区的superblock导入到内核当中,在OS内核当中构建出一个super block链表,这样就可以把每个分区管理起来;

 2.4 块列表

块列表就是inode中存放数据块编号的“数组”;

一般情况下,inode中的block数组的大小是15,那最多也才能存 60 KB数据啊?

如果不够存储怎么办?
考虑到这个原因,当然也有解决办法:

  • 0~12采用的是直接索引;
  • 13采用间接索引;比如:13保存一个数据块的编号,这个数据块不直接保存文件数据,4KB大小,它可以保存更多的块列表(其他数据块的编号),找到更多的数据块;
  • 14采用的是三级索引,和13的间接映射类似,多一级数据块进行存储块列表;这样单个文件的存储量是非常巨大的,但也有上限,一般来说是TB级别的;

对于二三十GB的文件(跨组存储),要如何存储?
        在映射时,块列表中不仅仅会存储数据块的编号,还会存储它所属块号、组号;这样就达到跨块访问、跨组访问;这个文件系统也叫Ext2文件系统;

但是问题来了,说了这么多,文件操作需要有inode编号,可以我们在日常使用时使用的都是文件名,没有用inode编号啊,这是什么原因?
        用户使用文件只会用文件名,而内核只认inode编号,所以文件名与inode之间必然存在相互映射关系;

test.c:1368

 3. 磁盘挂载

         磁盘可以被分为很多个区,每个区都有一个文件系统,那么在最开始的时候,我们如何判断文件在哪个分区?
        每个文件都有路径,可以通过路径前缀判断出在哪个分区;

        一个磁盘被分区格式化只后,就可以被使用了,默认情况下是不可见的,如果Linux要使用这个分区还需要进行挂载mount;

sudo mount dev/sdb1 /mnt
int fd = open("./log.txt","r”);

 比如一个进程要执行上述的代码:

  • 进程都有自己的工作目录(cwd),根据cwd结合传进来的文件路径,结合传入的相对路径,系统能够找到文件在磁盘上的确切位置;
  • 通过 cwd(或绝对路径的根目录)逐步查找路径中的每个目录,最终定位到文件所在的目录的 inode。
  • 文件inode被找到,将文件属性加载到内存,在内存中构造一个struct file结构体对象把inode属性填写到struct file中;
  • 然后就可以通过inode找到文件数据块,将数据块预加载到内存中,此时缓冲区就有了,读的时候将缓冲区内容拷贝到应用层,这样就拿到了文件数据;

4. 软硬链接

什么是软链接? 什么是硬链接? 为什么要有软硬链接? 它们的区别是什么?

ln -s 创建软连接,ln 默认创建硬链接;显示的数字2表示硬连接数(哪些文件名指向对应的inode);

删除硬链接映射的文件后,硬链接依然存在,并且它前边的数字变成了1;

一个文件什么时候,才算被真正的删除?没有文件名和inode映射(没有人用了)在系统层面,目标文件怎么知道没有文件名指向它了呢?

硬链接场景:

 新建一个文件夹,为什么它的硬链接数显示是2?

软连接和硬链接的区别:

  • 软连接是一个真正的文件,有自己的文件名和 属性以及内容
  • 硬链接就只是一对文件名和 inode 的映射关系,保存在目录中;

硬链接不是的文件,它是类似一个指向文件的指针;

软连接呢?


以上便是本文的全部内容,希望对你有所帮助,最后,感谢阅读!

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- gamedaodao.com 版权所有 湘ICP备2022005869号-6

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务