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