目录
前言
进程打开文件时,是否意味着系统内的所有文件都被打开了呢?
不是的,大部分文件不会被打开,那么没打开的文件又会被保存在哪里呢?
存储在磁盘,SSD中~按理来说OS是不会涉及磁盘内容的~
但为了让用户更快更方便找到文件,OS里的一个管理模块(文件系统)会专门来管理这些未打开的文件。
以类比进行举例:
我们平时存快递的菜鸟驿站就相当于磁盘,而菜鸟驿站的老板就是OS所属的管理模块之一(文件系统),通过有效的管理帮助用户快速查找未打开的文件~
磁盘的物理存储
磁头通过前后移动来遍历磁道,而盘面通过旋转让磁头读到不同的扇面,最终细分为扇区~
扇区通常是作为磁盘IO的基本单位,大小一般为512字节~
那么如果我们想访问磁盘中的一个扇区要怎么做呢?
- 首先通过磁头来定位磁面 Cylinder
- 其次再挑选用哪一个磁头(定位盘面) Head
- 最后在该盘面上访问扇区 Sector
- 我们通过CHS定位法来访问磁盘中的扇区
最终我们可以知道,在任何文件中,其实也就是多个扇区承载的数据~
磁盘的逻辑存储
通过以上步骤就可以把一个线性地址:123456789转化为CHS地址~
不过OS通常认为一个扇区大小为512字节太小了,4KB还差不多,那么我们就根据4KB大小进行微调~
计算扇区位置也不用担心,可以利用在第几个数据块快速定位~
既然我们已经认识到了数据块的存在,接下来我们进一步认识文件管理系统~
ps:文件名不属于文件属性!
可通过ll -i查看文件属性inode编号,所以在系统中,标识一个文件用的并不是文件名,而是文inode编号~
假设存储1w个文件
在学习以上内容后我们可以知道当我们要生成一个文件时,首先是要到inode Bitmap去挑选空闲可用的编号,然后往Data blocks存储内容,最后才是更新Block Bitmap与inode Table属性表~
而删除文件就是根据inode Table属性表里面的inode编号去inode Bitmap把相对应的比特位由1置0,再根据inode Table属性表里面的bolck块号去Block Bitmap把相对应的比特位由1置0,所以删除文件其实并不会去删除其文件属性与内容,而是把对应的位图进行修改~
接下来我们需要认识一个重点:inode编号是在整个分区内唯一的,并不是在分组内唯一~
所以当我们想要查看一个文件其内容属性的时候得先确定其inode编号在哪个组内,然后通过相对映射的方式到该组内找到其相对位置才能准确查到~
现在我们再回到int block[15]这个话题,那么多的数据块却只能存储15位,一块数据块4KB,那是否意味一个文件内容最多只有60KB的大小呢?
GDT的出现意味着管理分组只需要管理GDT即可~
如果GDT被破坏了,那只是该小组文件信息丢失,但如果是Super被破坏了,那是该分区文件信息丢失,这就需要格外重视了~
每个分区都可以写入相同/不同的文件系统~OS会管理多个文件系统,本质就是先描述该文件系统(Super),再组织起来统一管理~
最后我们再来谈谈文件名~
同样的如果我们想要查找一个文件例如aaa.txt,从Linux内核角度即从其归属目录中找,到归属目录的内容去找该文件名与inode编号,但目录本质也是一个文件从目录查找文件aaa.txt其实也就是在查找归属目录,这就陷入了一个鸡生蛋,蛋生鸡的矛盾场景~
不过最终会找到根目录,因为根目录的Inode编号是确定的,所以查找一个文件,在内核中,都要逆向的递归般得到/,从根目录进行路径解析。当然在这个逆向递归的途中若是有一个文件权限无X(无法进入目录)那最终也无法查到aaa.txt了~
我们再来回归主题~既然inode是在分区内有效,那我们的文件如何确定在哪个分区呢?
一个被写入文件系统的分区,若要被Linux使用,必须要先把这个具有文件系统的分区进行“挂载”,而所谓挂载其实也就是让分区与目录建立一层联系~
就比如我们把分区挂载到top目录下,/top,那么top目录往下的所有内容都在这个分区中,在top目录下可以去访问该分区~
这样看来我们磁盘中的分区本质上也可以看作是一个个的目录~
访问一个文件,就可以根据路径的前缀,优先区分出文件在哪一个分区下~
既然是通过路径索引文件,那我们为何单靠文件名就可以访问文件了呢?
明明没有给路径,系统又是如何知道在哪个分区并且找到文件的呢?
首先我们打开文件(open,fopen)都是需要我们提供路径的,当然这不是重点,重点是当我们执行命令的时候,进程产生时就自动记录当前路径了,所以我们才可以通过文件名直接访问,因为进程产生的当前路径会自动与文件名拼接进而被查找到~
软硬链接
ln -s软链接
软链接本质就相当于快捷方式,加速找到目标文件~并且链接后本质是一个文件,有独立的inode,其内容里面放的是目标文件的路径~
ln 硬链接
硬链接本质不是一个独立的文件,因为它的Inode编号和目标文件相同,相当于只是在目录内容中多了一条文件名与inode编号的映射方式,可以理解为c++中的引用~
而删除文件的本质就是利用引用计数来看硬链接数,只有当硬链接数减为0的时候才会真正把该文件对应的位图清空~
因此硬链接本质上是在指定目录下插入新的文件名与目标文件的映射关系,并让Inode的引用计数++~
那问题来了,为什么新建的空目录硬链接数反而是2呢?难道它还有其他的别名?
空目录中除了自身文件名,.也是属于当前目录,所以空目录创建后才会有2个硬链接数
当我们再往dir目录下创建目录后,它的硬链接数又增加了,因为..是作为上一级目录,本质上也是目录dir~
不过我们自己给目录建立硬链接是不允许的,这样会形成环路问题,只有系统才能自己给目录建立硬链接,所以.与..系统可以识别出来,可以避免环路,但我们自定义的就识别不出来了~
ps:一个目录下有多少个子目录:硬链接数-2~