在 “L29 从生磁盘到文件” 中,第三层抽象是建立文件字符流和盘块集合之间的映射(inode),但这是针对单个文件来说的(一个文件映射到一堆盘块);而在本章中,则要讲述第四层抽象——能找到对应于目录的文件,将整个磁盘抽象成一个文件系统,对应于一棵文件目录树(一堆文件映射到整个磁盘)。
★文件系统,就是将整个磁盘的盘块抽象成一棵文件目录树。
L31 目录与文件系统
文件系统
在 “L29 从生磁盘到文件” 中,第三层抽象是建立文件字符流和盘块集合之间的映射(inode),但这是针对单个文件来说的(一个文件映射到一堆盘块);而在本章中,则要讲述第四层抽象——能找到对应于目录的文件,将整个磁盘抽象成一个文件系统,对应于一棵文件目录树(一堆文件映射到整个磁盘)。
★文件系统,就是将整个磁盘的盘块抽象成一棵文件目录树。
目录的产生
操作系统的目录并不是直接得到一棵目录树,而是通过一次次的演变得到的。
最开始的 “目录” 是所有文件都放在一层,但是一个操作系统有成千上万个文件,所以要找到具体的一个文件就会很耗时,于是进行演变,采用集合划分、分治的思想,对这些文件进行划分;
所以考虑让多个用户分别处理所有文件中的一部分,但实际上每个用户需要处理的文件还是非常多,所以进一步演变,演变成目录树。
在有了目录树之后,操作系统就可以根据目录树快速地找到对应的文件,再结合前面所述的 inode、
file+count
、盘块号、生磁盘的使用等,就可以实现从文件到磁盘的使用了。于是接下来的问题就是,如何实现目录树的形成。
★目录的实现
目录的实现的最终目的,就是如下图所示的,能根据
/my/data/a
,得到文件 a 的 FCB(即 inode )。在上图中,
my
目录下有三个文件(data
目录也是一个文件,只不过这个文件中又包含有两个文件):data
、cont
、mail
。那么该如何确定具体是哪个文件呢?即如何确定在
my
目录下要找的是data
目录文件、cont
文件或者mail
文件呢?这就需要用 FCB 来标识具体的文件,所以在my
目录下就应该有data
目录文件的 FCB、cont
文件的 FCB、mail
文件的 FCB。但在实际的操作系统中,却不是用这种方式来在目录中找到具体的文件的,因为这种寻找方式需要把
my
目录下的所有文件的 FCB 先读取出来,然后根据名称找对应的 FCB(解析my
的内容),速度是比较慢的,所以需要用下面的方法来提高文件系统的效率。如下图所示,对每个目录(目录也是一个文件,目录文件),都有一个目录项,其中的整数用来表示该目录的 FCB 在磁盘 FCB 数组的哪个位置,根据目录项中的整数就可以得到该目录的 FCB,再根据其 FCB 就可以得到对应的数据盘块,从数据盘块中,就能进一步得到该目录中各个文件的目录项,以此类推,最终就可以得到目标文件的目录项,继而得到目标文件的 FCB。
注意:起始的目录,即根目录的 FCB 的位置是需要在初始化时设置好的,所以根目录的 FCB 的地址应该存储在磁盘信息里。
如下图所示,首先在固定大小的引导块中进行磁盘的引导,然后到超级块,在超级块中记录有 inode 位图和盘块位图的信息,在得到了 inode 位图和盘块位图的大小后,就可以计算得到根目录的 FCB 的位置了。
★★★文件使用磁盘的全过程
到此,从文件到磁盘的使用的全部过程就阐述明白了,进行一个总结:
- 首先,用户给出文件路径,通过文件系统的目录解析,就找到要操作的那个文件
file
,也即找到了文件的 FCB; - 在得到了文件的 FCB 后,再加上
file+count
,就可以得到对应于具体那一段字符的盘块号; - 有了盘块号以后,操作系统就根据电梯算法将盘块号插入到电梯队列中;
- 磁盘从电梯队列中得到盘块号,向 CPU 发出中断;
- CPU 进行中断处理,根据盘块号算出 CHS,并通过 out 指令把 CHS 发送给磁盘控制器;
- 磁盘控制器根据 CHS 找到磁盘上对应的那一个扇区,并对其进行操作;
- 等磁盘控制器对扇区的操作结束以后,磁盘又向 CPU 发出中断,CPU 进行中断处理,唤醒因将盘块号插入电梯队列而睡眠的进程。
- 首先,用户给出文件路径,通过文件系统的目录解析,就找到要操作的那个文件