前言
我们在之前的文章中讨论的都是进程和被打开的文件的关系,但是如果一个文件时没有被打开,它是否需要被管理?它该如何被管理呢?
本文介绍了文件存储的位置:磁盘,它的三种结构(物理结构、存储结构以及逻辑结构);管理文件的结构:文件系统与inode;以及文件与inode之间的关系:软硬链接等相关概念。
一、磁盘
磁盘是计算机的主要存储介质,它可以存储大量二进制数据,即使断电后也可以保证数据不会丢失。下面我们将了解磁盘的物理结构、存储结构以及逻辑结构
1.磁盘的物理结构
磁盘是外设,他也是计算机中唯一的机械结构(访问外设相对较慢的原因就是机械结构的运行速度比电流的运行速度慢)。
磁盘的盘片和盘面类似于光盘,不过磁盘是两面都是光面,光盘只有一面(盘面上存储着数据)。
像刀子一样的是磁头(每一面都有一个磁头),磁头与盘面(两者每一接触)之间有马达。一旦盘片加电,盘片旋转,磁头摆动,马达可以控制磁头摆动,控制盘片旋转。
对应的磁盘有自己的硬件电路,通过硬件电路 + 伺服系统,给磁盘发送二进制指令,让磁盘定位寻址盘面上的某个区间。
2.磁盘的存储结构
- 磁盘寻址的时候,其基本单位既不是bit也不是byte,而是扇区。
- 扇区的大小:521字节,521字节是硬件要求,对于外磁道和内磁道来说大小都是一样的,它们只是密度不同。越靠近圆心的比特位越大,外侧的比特位较小。
- 在单面上定位扇区:通过确定磁道,以及确定对应磁道的扇区,来具体确定该区间。确定磁道:每一个磁道都有自己的编码,磁道周长不同,但是存储大小相同。由于扇区大小是相同的,因此每一个磁道有多少个扇区也是一定的,所以每一个磁道的扇区也是有编号的,因此定位到磁道就能找到对应扇区。
- 机械硬盘的寻址方式:盘片不断的转动,磁头不断的摆动,就是在确认在哪个磁道。如何确定扇区?盘片的先选择就是让其磁头定位扇区。
- 柱面:把一系列同心的磁道压在一起,宏观上看成一个整体。一般定位的时候,(磁头、柱面、扇区)与(磁头、磁道、扇区)这两个是等价的。磁头指向的位置就是柱面的边界位置。
- 在磁盘中定位扇区:先定位在哪个磁道(在哪个柱面),磁道定位后,(因为,所有磁头共同进退)再去定位盘面(磁头),最后确定是哪一个扇区。
总结:在磁盘中定位一个扇区,采用硬件级别定位方法(CHS定位法):柱面(Cylinder)——磁头(Head)——扇区(Sector)
3.磁盘的逻辑结构
我们都见过磁带(复读机等机器用过),它卷起来是圆柱,将它拆开就是一条很长的线。
我们可以将磁盘盘面想想成类似的结构。站住OS的角度,它认为磁盘的盘面是线性结构,它为每一个扇区划分好了空间,整个磁道相当于一个数组。要访问某个扇区,只需要定位到对应的数组下标。在操作系统内部,我们将这种地址称为LBA(Logic Block Address),如果要将它写在磁盘上,则我们要将对应的LBA转化为对应磁盘的三维地址:CHS地址。
总结:OS中的地址为LBA,对应的磁盘地址为CHS地址。
由于OS要进行逻辑抽象,不直接使用CHS,原因:
- 便于管理,管理数组和管理三维立体结构两者之间,数组更好管理;
- 让OS的代码和硬件磁盘解耦(避免它们之间强耦合)。例如:磁盘的基本大小(每个扇区对应的存储空间)发生改变,OS的源码也要发生改变吗?我们当然不需要OS的源码发生改变。
二、文件系统与inode
1.文件在磁盘中是如何存储的?
文件在磁盘中,而磁盘的逻辑结构是线性结构。磁盘的空间很大,OS内文件系统会定制多个扇区进行读写,以1KB、2KB、4KB为单位,即使读取/修改1bit的内容,也必须将4KB的内容加载到内存中进行读取或修改,完成操作后再将其写回磁盘。虽然磁盘的访问的基本单位是521字节,但是还是相对于整个磁盘的大小还是很小的。
为了方便管理,我们采用分治的思想,对磁盘空间进行分区:1个较大的磁盘空间 ——> 多个较小的磁盘空间,再给不同的分区写入不同的文件系统。
- Boot Block是启动块,存在每个分区的开头,备份与启动相关的文件;
- 将剩余的空间继续分组,Block group 0 …… Block group n。管理好Block group 0,其他的也可以管理好,因此我们需要了解Block group 0;
- Super Block:保存的是整个文件系统的信息,为什么Super Block不能像Boot Block一样存在与每个分区的开头?
将Super Block保存在不同的分组中是为了备份,假如某个Super Block损坏,我们可以通过拷贝其他分组的Super Block来修复它。 - Linux的文件 = 内容 + 属性。Linux的文件内容和属性是分批存储的。文件属性保存在inode中,inode的大小是128字节,是固定的。一个文件有且仅有一个inode与之对应。inode中存储文件几乎所有的属性,但是文件名并不在inode中存储。文件内容存储在data block块中,不同的文件,文件内容是不同的,大小也不同。
- inode为了区分彼此,每一个inode都有自己的ID,我们可以通过指令
ls -li
来查询文件对应的inode编号。 - inode table保存分组内部所有的可用(已经使用 + 没有使用)inode。
- Data blocks 保存分组内部所有文件的数据块(保存文件内容)。
- inode Bitmap:inode对应的位图结构,统计inode的使用情况,位图中比特位的位置与当前文件对应的inode的位置是一样对应的,比特位为1说明该inode已经被占用,否则表示未被占用(即,可以被使用)。
- GDT(group descripteor table):块组描述表,对应分组的宏观的属性信息,inode有多少个,已经使用多少,已经被占用多少个,还剩下多少个。
- 查找文件时,统一用的是inode编号。
文件内容放在data blocks中,文件属性保存在inode中,而inode内部有一个数组,保存对应data blocks块的编号,二者就联系起来了。
如果文件特别大,并不是所有的data blocks都只能存储文件数据,它也要存储其它块的块号,所以一个blocks块会指向其它多个blocks来存储文件数据(这样能存更多)。
2.对文件进行操作
- 创建文件:位图的比特位由0置为1,找到其inode table,将文件属性填进去,文件的数据写入data blocks中,建立inode和block之间的映射关系;
- 查找文件:拿到inode找到对应的inode table,根据inode table 找到对应的数据块,就拿到了文件的内容 + 属性;
- 删除文件:删除文件只需要找到inode在inode bitmap中的比特位,然后将该比特位由1置为0即可。
- 恢复文件:
删除文件并不需要将文件的数据和内容情况,只需要将对应文件的inode在inode bitmap中的比特位 置为0即可(即使不将它们清空也不会影响新文件的存储,因为新文件的数据会直接将原数据覆盖掉)。因此,在删除文件后是可以及时将文件恢复的,恢复文件只需要找到inode的编号,然后把inode bitmap里对应的比特位由0置为1,再去inode table对应映射表,将blosk bitmap由0置为1即可。
如果在Linux中误删一个文件,还是可以恢复的,前提是文件的inode和data block没有被占用,因此当误删一个文件时最好的做法是什么也不做。
在windows下,删除文件到回收站,实际上是将文件转移到回收站的目录而已,只有在回收站中删除才是真的删除。
为什么我们在目录中查找文件时,用的是文件名而不是inode?
因为任何一个文件都是创建在目录下的(注意,同一目录下不能出现相同文件名的两个文件),目录也是一个文件,也有自己的inode,以及data block。目录的数据块(data block)中存储的是当前目录下的文件的文件名与文件的inode的对应关系(这也是为啥inode中不保存文件名)。
新增文件要向当前目录的内容(data block)中写文件名与inode的映射关系,所以当我们在一个目录下新增文件时,必须要有对目录的写权限。
罗列当前目录的文件,要有对目录的读权限,想知道目录中的文件,需要根据文件名找到inode,再读取该文件的属性,读目录内容是拿到文件名,因此目录必须要有读权限。
三、软硬链接
1.软链接
创建软链接:
ln -s myfile.txt soft_file.link
文件myfile.txt
文件soft_file.link
inode
可以从上图中看到,soft_file.link是具有自己独立的inode,因此它是一个独立的文件,具有自己独立的内容。
所谓的软链接标定文件,它并不是用文件的inode来标记。看这个现象:我们删除myfile.txt然后再去cat soft_file.link:
软链接并没有用目标文件对应的inode,而是用目标文件的文件名,软链接的数据块中保存的是指向目标文件的路径,当目标文件被删除时,软链接也就失效了。
删除软链接:
- rm
rm -f soft_file.link//和删除普通文件一样
- ulink
ulink soft_file.link//删除链接
软链接的作用:
软链接就类似于windows下的快捷方式(桌面的软件图标就是该软件exe的快捷方式,软件实际上的存储位置并不在桌面,我们可以通过快捷方式直接去执行该exe文件)。
当执行路径非常深,导致路径非常长不方便记忆,因此我们可以通过软链接来访问文件,这样就不用每次都输入长长的路径来访问文件。
2.硬链接
创建硬链接:
ln myfile.txt hard_file.link
inode
可以发现,硬链接没有独立的inode,它的inode是目标文件的inode,因此它不是一个独立的文件。
硬链接的作用?
当硬链接的其中一个文件的大小和内容发生变化,那么它对应的目标文件以及所有目标文件的硬链接都会一起发生改变。硬链接没有创建新的文件,它没有独立的inode、属性、内容。它用的全部是目标文件的inode和内容。
创建硬链接的本质就是在指定的路径下,新增文件名和inode的映射关系。
一个inode可能会被多个文件名所映射,为了方便管理,inode有一个计数器,count的引用计数,将引用计数称为硬链接数:
这也是为什么我们发现数字由1变为2了,此时inode被两个文件名所指,因此硬链接数变为2。
删除硬链接
如果把硬链接的目标文件删除,目标文件:
inode的引用计数变为1,即去掉了一组映射关系。
只有当文件的硬链接数变为0时,该文件才是真的被删除了。
硬链接的作用
- 为啥创建一个普通文件时,硬链接数是1?
因为,普通文件本身就有一个文件名和inode对应(只要创建文件,就有一个inode的映射关系)。 - 为啥创建一个目录,它的硬链接数是2?
因为目录于它自己的inode就是一组1映射关系;其次,目录内部的'.'
('.'
也表示当前目录,它也是文件名)和inode也是一组映射,所以硬链接数是2。
特别的,在当前目录下创建再一个目录,当前目录的硬链接数会变为3,因为当前目录下创建的哪个目录中默认的文件名'..'
('..'
表示上一层目录,它也是文件名)和inode也是一组映射。
上面的是2,原因是在创建dir2之前打开的,因此没有及时更新,我们看最下面的结果(硬链接数为3)即可。
目录不能自定义建立硬链接
我们发现Linux不允许普通用户给目录建立硬链接。
这是为什么呢?
我们知道,Linux默认会给目录建立两个硬链接:'.'
和'..'
。
假如,我们是root(超级用户),系统允许超级用户给目录创建硬链接。我们给根目录创建硬链接,新创建的硬链接的文件名从根目录开始查找,查找到的硬链接就是根目录,此时就造成了递归式查找(环形查找),导致软件无法正常进行查找。因此不允许普通用户给目录建立硬链接。
总结
以上就是今天要讲的内容,本文介绍了磁盘的三种结构、文件系统与inode以及软硬链接的相关概念。本文作者目前也是正在学习Linux相关的知识,如果文章中的内容有错误或者不严谨的部分,欢迎大家在评论区指出,也欢迎大家在评论区提问、交流。
最后,如果本篇文章对你有所启发的话,希望可以多多支持作者,谢谢大家!