大家好我是沐曦希💕
一、前言
我们知道一个被打开的文件,操作系统为了管理文件必定要为文件创建对应的内核数据结构来标识文件struct file{};
那么如果一个文件没有被打开,该如何被OS管理呢?没有被打开的文件只能在磁盘上放着。磁盘上面有大量的文件,也是必须要静态管理起来的,方便我们随时打开!
那么就要提到文件系统和磁盘了!
二、磁盘
磁盘是计算机主要的存储介质,可以存储大量的二进制数据,并且断电后也能保持数据不丢失。
1.物理结构
磁盘是外设并且是计算机中的唯一的机械结构(访问相对较慢)
虽然在日常生活中我们很少见到磁盘,但是磁盘在企业里面用来存储数据依旧是主流。
磁盘的盘面/盘片的表面涂有磁性物质,这些磁性物质用来记录二进制数据。因为正反两面都可涂上磁性物质,故一个盘片可能会有两个盘面。而像刀子一样的是磁头(每一面都有一个磁头),磁头和盘面并没有接触,磁盘必须防止抖动。(因为一旦磁头接触磁盘有可能会刮花磁盘,导致磁盘存储的二进制数据出现错误)
中间有马达,一旦盘片加电之后,盘片旋转,磁头摆动,马达可以控制磁头摆动,控制盘片旋转。对应的磁盘也有自己的硬件电路,通过硬件电路+伺服系统,给磁盘发二进制指令,让磁盘定位寻址某个区域。
2.存储结构
磁盘寻址的时候,基本单位不是bit(更不是byte),而是扇区
扇区的大小:512字节,512字节是硬件要求,对于外磁道和内磁道大小都是一样的,密度不一样。越靠近圆心的比特位越大,外侧的较小。
在单面上定位扇区:通过确认磁道,最终确定在对应磁道的哪一个扇区。确认磁道:每个磁道都有自己的编号,磁道周长不一样,但是存储大小是一样的,因为扇区大小一样,一个磁道有多少扇区也是固定的,所以每个磁道的扇区也有编址。所以定位到某个磁道上就能够找到。
机械硬盘的寻址方式:盘片不断旋转,磁头不断摆动,就是在确认在哪一个磁道;如何确定在对应磁道的哪一个扇区呢?盘片也在旋转,就是让磁头定位扇区。
每一个盘面都有一个一个磁头,所以磁头的个数和面数相等。磁头都是连接同一个马达的,所以磁头是共进退的。每一个磁道都可以看成是一个柱面
柱面:把一系列同心的磁道压在一起,宏观上看成一个整体。一般定位的时候:磁头、柱面、扇区 ==(磁头、磁道、扇区),这两个是等价的。柱面相当于磁头一起指向的位置就是柱面的边界位置。
在磁盘中定位任何一个扇区:先定位在哪一个磁道(哪个柱面),磁道确定,所有磁头共进退,此时磁头不动,在去定位磁头(定位盘面),最后在定位哪一个扇区。
总结:磁盘中定位任何一个扇区,采用的硬件基本的定位方式: CHS定位法! 柱面Cylinder——磁头Head——扇区Sector
3.逻辑结构
磁盘在物理上是圆形的,都是我们可以把它想象成线性结构
我们可以把整个磁盘从逻辑上看做成为一个sector arr[n]数组,要访问某个扇区,只需要定位数组下标,也就是说知道这个扇区的下标就算定位了一个扇区。在OS角度,把磁盘看作线性结构,从而对磁盘进行管理,就是对数组进行管理。
那么只要知道这个扇区的下标,就可以定位到一个扇区!!在操作系统内部,我们称这种地址为 LBA(Logic Block Address)地址
而要写到物理磁盘上,我们就要把LBA地址转换成对应磁盘的三维地址CHS地址。总结来说,OS的地址为LBA地址,而对应的磁盘为CHS地址。
为什么OS要进行逻辑抽象呢?直接用CHS不行吗?
- 方便管理,管理数组与管理三维立体结构,数组比较好管理
- 不想让OS的代码和硬件强行耦合!不想因为硬件的数据的改变,而让OS代码随之改变
三、文件系统——inode
文件在磁盘中是如何存储:文件是在磁盘中的,而逻辑结构是线性结构。
磁盘的空间很大,虽然对应的磁盘的访问的基本单位是512字节,但是依旧很小!!!OS内的文件系统定制的进行多个扇区的读取,以1kb,2kb,4kb等为基本单位进行读取,所以哪怕只想读取修改1bit,都必须将4kb数据加载到内存,进行读取或者修改,如果必要再写回磁盘!!
例如:ls -l读取存储在磁盘上的文件信息,然后显示出来
采用分治的思想,来管理磁盘空间进行分区:大的磁盘空间->小空间,给每个分区写入不同的文件系统。
采用局部性原理,内存是被划分成为4kb大小的空间——页框
磁盘中的文件尤其是可执行文件——按照4kb大小划分好的块——页帧
Boot Block是启动快,存在每个分区的开头,备份文件与启动相关的。
将剩下的空间继续分组,Block group 0…Block group n。管理好Block group0,其他的也能管理好,所以我们只需要了解Block group 0。
Super Block:保存的是整个文件系统的信息,Super Block保存在不同的分组里意味着有多组备份,如果某个Super Block损坏,便可以通过拷贝其他分组的Super Block。
在Linux下文件=内容+属性,而Linux的文件属性和文件内容是分批存储的!!保存文件属性的是inode,inode块的大小是固定的,为128字节。一个文件,一个inode,包含文件几乎所有的属性,文件名并不在inode中存储。文件内容存储在data block块中,不同的文件文件内容不同,data block大小随着应用类型的变化大小也在变化。inode为了进行区分彼此,所以每一个inode都有自己的ID,这里我们利用指令ls -li(显示每一个文件对应的inode编号)查看inode编号:
inode table:保存了分组内部所有的可用(已经使用+没有使用)的ionde
data block:保存的是分组内部所有文件的数据块
inode Bitmap:inode对应的位图结构,位图中比特位的位置和当前的inode的位置是一一对应的!!比特位为1,代表inode被占用,否则表示可用。
Block Bitmap:数据块对应的位图结构,位图中的比特位位置和当前data block对应的数据块的位置是一一对应的
Group Descriptor Table(GDT):块组描述表。对应分组的宏观属性信息,已经使用多少,inode有多少个,已经被占用了多少个,还剩下多少个。
查找一个文件的时候,统一使用的是:inode编号
内容放在data blocks中,属性在inode table中,而inode内部保存了一个数组,保存对应块的编号,二者就联系起来了:
并不是所有的data block只能存放文件的数据,也可以存放其他块的块号,所以最终指向更多的block来存储
创建一个文件:在位图的比特位由0置为1,找到其inode table,属性填进去,文件的数据写到block里,在inode和block建立映射关系,最后返回inode编号,创建成功
查找一个文件:拿到inode找到inode table,在根据inode table找到对应的数据块,内容加属性就全找到了
删除一个文件:删除文件也需要用到inode,实际上删除一个文件时,我们只需要找到inode在inode bitmap当中的比特位,把比特位由1置为0就删除了。所以删除一个文件根本不需要把数据属性和内容清空,只要把inode bitmap的1置为0,属性就删除了,这个文件也占着数据块,也把block的比特位也置为0。所以文件删除是能够恢复的,一旦删除只是把bit位清掉了,想要恢复只要得到inode的编号,然后把inode bitmap里的比特位由0置为1,在去inode table对应的映射表,在block bitmap的0置为1。
如果在Linux中误删除一个文件,还是能恢复的,但是前提必须是inode和data block没有被占用,所以当误删除一个文件时,最好的办法就是什么都不做。而我们在Windows中删除文件到回收站,只是转移了目录,在回收站中删除才是真正的删除。
可是我们在查找一个文件的时候,用的不是inode,而是文件名?
任何一个文件都在一个目录下,但是这些文件并没有重复的文件名。
目录是一个文件,也有自己的inode,有对应自己的data block,目录的数据块存放的是当前目录下的文件名和inode的映射关系,所以inode并不需要保存文件名。
所以我们在一个目录下新增一个文件,必须得有写入权限,新增一个文件的时候,要向当前目录的内容里去写文件名和inode的映射关系,所以必须得有写入权限。罗列当前的文件,要有读权限,想读的时候要根据文件名找到inode读取底下的所有文件的属性,读的是拿到文件名,必须得去访问数据块,所以要有读权限。
1.补充
还有一个stat命令能够看到文件更多信息:
Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。政府管理各区的例子
超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了。
GDT,Group Descriptor Table:块组描述符,描述块组属性信息。
块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用
inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。
i节点表:存放文件属性 如 文件大小,所有者,最近修改时间等
数据区:存放文件内容
将属性和数据分开存放的想法看起来很简单,但实际上是如何工作的呢?我们通过touch一个新文件来看看如何工作。
[lj@VM-8-2-centos mystdio]$ touch abc
[lj@VM-8-2-centos mystdio]$ ls -i abc
263466 abc
为了说明问题,我们将上图简化:
创建一个新文件主要有一下4个操作:
- 存储属性
内核先找到一个空闲的i节点(这里是263466)。内核把文件信息记录到其中。- 存储数据
该文件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。将内核缓冲区的第一块数据复制到300,下一块复制到500,以此类推。- 记录分配情况
文件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。- 添加文件名到目录
新的文件名abc。linux如何在当前的目录中记录这个文件?内核将入口(263466,abc)添加到目录文件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来
四、软硬链接
1.软链接
软链接是通过名字引用另外一个文件
- 创建软链接
ln -s 要软链接的文件名/地址 软链接名字
软链接获得的是一个独立的文件,有自己的独立inode,,独立的文件有独立的inode和对应的文件内容。
软链接标定一个文件,靠的是目标文件的文件名,不靠目标文件的inode,我们删除myfile.txt,然后再去cat soft_file.link:
把文件删了找不到,软链接的数据块里保存的是所指向的目标文件的路径,所以目标文件一删,软链接也就失效了。
删除软链接:既可以rm,也可以用unlink:
软链接相当于快捷方式,软链接的作用:
当执行路径非常的深,导致路径非常的长,我们可能会忘记路径,所以我们可以通过软链接不用每次都输入长长的路径,可以通过软链接而快速找到:
相当于windows下的快捷方式:
2.硬链接
硬链接是通过inode引用另外一个文件
- 创建硬链接:
ln 要硬链接的文件名/地址 硬链接名字
软硬链接有什么区别:是否具有独立的inode!!
软链接具有独立的inode–可以被当做独立文件看待
硬链接没有独立的inode–指向到其他文件的inode,不是独立的文件
建立一个硬链接是在做什么?
当硬链接其中一个文件的大小、内容等发生变化,那硬链接的文件都会发生相应的变化,所以建立硬链接根本没有新增文件,因为没有给硬链接分配独立的inode,既然没有创建文件那么就没有自己的属性集合和内容集合,用的是别人的inode和内容。创建硬链接本质就是在指定的路径下,新增文件名和inode编号的映射关系!
inode可能会被多个文件指向,所以inode有一个计算器,count的引用计数,把引用计数称为硬链接数:
这也是我们为什么能看到1变为2的原因,因为有了新的文件名,inode被两个文件所指向,硬链接数变为2了.
删除myfiletxt,软链接失效,但是硬链接不失效,引用计数-1:
所以一个文件被真正的删除是当一个文件的硬链接数变为0的时候,这个文件才算被真正的删除。
而创建软链接是不增加文件的引用计数的
- 硬链接作用
可以看到普通文件硬链接数是1,目录硬链接数是2
因为一个普通文件本身就有一个文件名和自己的inode,具有一个映射关系!
首先目录和本身的inode就是一组映射关系了,另外,第二个是目录内部的.(.表示当前目录,也是文件名。inode是一样的)和inode也是一组映射,所以是硬链接数是2
在empty目录下创建一个dir目录,其硬链接数是2:
可以看到empty硬链接数变成了3,因为die目录中有一个…代表上级目录,代表一次硬链接
但是Linux不允许普通用户给目录创建硬链接,但是可以创建软链接:
. 和 … 是系统创建的,给目录建立的硬链接。
五、写在最后
软硬链接本质区别就是有无独立的inode.
acm时间:
Access时间:文件被访问时间,因为访问会太频繁,而文件的数据在磁盘,进行更改效率太低了,所以Linux优化其更改机制
Modify时间:文件被修改时间:内容最后被更改的时间
Chang时间:文件被更改时间:属性最后被修改时间