文件系统从上往下分为了五层,分别是用户调用接口、文件目录系统、存取控制模块、逻辑文件系统与文件信息缓冲区、物理文件系统。
在操作系统中,目录实现主要有两种方式:
线性列表是一种常见的数据结构,有链表和数组两种。我们将FCB(文件控制块)中的信息简化为文件名与文件索引节点指针后,文件的目录结构如下:
哈希表依赖于哈希算法,是一种散列算法,文件名进行哈希计算后得到一个值,将这个值作为索引。相较于线性列表,哈希表的方式使得文件名与索引之间建立了一种映射关系,查询效率更高。
文件最终是保存在磁盘上,磁盘的存储单位通常以一个固定大小作为分区(比如4K)。这样整个磁盘就被分为了很多个大小一致的盘块。
连续分配的概念很简单,就是文件在分配到磁盘时,所分配的盘区是连续的。在保存文件存储地址时,只需要保存起始块号以及所占用的块号数量或者结束块号即可。
这种方式实现简单,访问速度块。但是不方便扩展(比如一个文件分了0、1、2后还需要继续追加文件内容,3号块已被占用,就导致无法扩展),同时还有有大量的磁盘碎片。
链接分配,其实就是采用了链表这一数据结构来实现文件的存储。 因此我们需要额外的开销来保存每个盘块的下一个盘块信息。
如果下一个盘块的信息保存在盘块内,称之为隐式链接。
但是对于脆弱的机械磁盘而言,一旦收到轻微损伤,导致某一盘块中的链接信息丢失,将会导致整个链表断开,从而丢失文件。针对这个问题,提出了显式链接。
显示链接将链表的下一盘块信息提取出来进行专门的维护,即:FAT文件分配表。在FAT中,如果下一块号为**-1**,表示该号块是链表的最后一个块号。-2表示当前块号是空闲状态。
链接分配意味着操作系统需要将FAT表加载至内存,如果磁盘很大,盘块很多,其实还要占用较大的内存空间。为了优化这个问题,就提出了索引分配方式。
索引分配,存放的是文件名对应的索引块号,而不是其实块号。根据索引块号找到对应的盘块,该存储索引数据的盘块保存着文件的索引表,由逻辑块号和物理块号组成。
以上图为例,文件的索引表是一个数组,数组的每个值是一个整数,占4B。由于每个盘块大小为4K,因此一个盘块最多能存放1024个索引。即一个索引块最多关联1024个盘块,也就是4M。
4M对于文件而言,实在太小了,毕竟很多文件动辄几百兆甚至上G。因此一个文件必须多个盘块作为索引表的存储载体。
结合文件的分配方式,可以采用链接分配方式,即多个索引表的盘块使用链表结构进行连接。
相较于链接方式,与操作系统内存分配方式类似,可以采用多级思想,即使用多级的索引结构。如果使用二级索引,则最多可以存储1024个一级索引1024个二级索引4K=4G文件。
当然,上图展示的二级索引基础上还可以优化,比如将二级索引表中的热点数据直接存放于一级索引表中,可以提升文件读取效率。这种方式称为混合索引。
文件分配方式针对的是已分配的文件以及对应的磁盘空间。而文件存储空间管理,针对空闲的磁盘空间的管理。
物理磁盘通常会在逻辑上分成多个区域(比如卷C、卷D),而每个分区中又会分为目录区、文件区。目录区所存储的是数据结构(如FCB);文件区存放的是文件的数据。
空闲表法就是将磁盘中那些空闲的盘块信息记录在空闲盘块表中。如果使用数组结构就是空闲表法,如果使用链接结构就是空闲链表法。
对于空闲链表法,如果把每个空闲盘块链接起来,称为“空闲盘块链”;如果结合空闲表法,将空闲表法的空闲盘块表的每项数据通过链表保存,称为“空闲盘块链”。
但是这两种方式在面对大量盘块时,链表过长,这些数据结构要加载到内存中导致占用内存空间大且效率不高。
成组链接发,使用链表以及栈的数据结构。每个空闲盘号栈存放了固定数量的空闲盘号数据。
系统启动时,会将第一组连续的空闲扇区(根据超级块)加载入内存中,在进行盘块分配时依次出栈,到栈底时根据栈底盘号元素中保存的数据链接到下一空闲盘号栈。
盘号回收的时候,在一个已有的空闲盘号栈装满后,新构造一个空闲盘号栈,然后将其添加到整个链的最前面。
整个流程的示意图如下:
位示图法就是构建一个二维表,每个坐标表示一个盘块,用0表示对于盘块空闲,1表示对应盘块已分配。
其说明如下图: