空闲盘块栈与成组链接法的关系:核心与框架
核心关系:
空闲盘块栈是实现成组链接法在内存中的核心组件和高速缓冲区。成组链接法是一种宏观的、旨在高效管理整个磁盘空闲空间的算法框架,而空闲盘块栈则是这个框架在内存中进行快速操作的具体实现手段。它们是整体与部分、框架与核心的关系,而非两种并列的方法。
可以这样比喻:
-
成组链接法好比一个大型物流公司的整套仓储管理系统。
-
空闲盘块栈则是这个系统在每个发货点设置的**“快速拣货区”**。
这个“快速拣货区”(空闲盘块栈)地方不大,但存放着最常用、即将要发出的货物(空闲块编号)。绝大多数订单(分配请求)都能在这里快速完成。当拣货区空了,系统才会启动一个流程,去远方的大仓库(磁盘上的其他空闲块组)调拨一整批货过来补满。反之,退货(回收块)也优先放回这个拣货区,满了之后再整批运回大仓库。
成组链接法是如何使用“空闲盘块栈”的
成组链接法通过在内存中的超级块(Superblock)里实现一个固定大小的、小规模的空闲盘块栈,来处理日常的分配与回收。这个栈就是它对“空闲盘块栈”思想的直接应用。
下面是它使用这个内存栈的完整工作流程:
1. 初始化与结构
-
内存中的组件: 在文件系统的超级块中,有一个我们称之为**“当前可用栈”的区域,它就是一个空闲盘块栈**。这个栈的大小是固定的,比如
N
(通常为100)。 -
磁盘上的组件: 磁盘上剩余的所有空闲块被分成若干“组”,每组的第一个块(头块)记录着组内其他空-闲块的地址和指向下一个组的指针。
-
链接: 内存中“当前可用栈”的栈底,始终保存着指向磁盘上第一个空闲块分组的“头块”的地址。
2. 分配空闲块时,如何使用内存栈?
当一个进程需要一个空闲块时:
-
检查内存栈: 系统首先查看“当前可用栈”是否为空。
-
情况A:栈不为空(最常见的情况)
-
直接对内存栈执行出栈操作,从栈顶弹出一个空闲盘块的编号。
-
将这个编号返回给请求者。
-
优势体现: 这个过程完全在内存中完成,速度极快,无需任何磁盘I/O。这就是“空闲盘块栈”带来的核心好处。
-
-
情况B:栈为空(需要与磁盘交互)
-
内存栈中的“快速拣货”已经用完。
-
系统从内存栈的栈底取出之前保存的“下一组头块”的地址。
-
启动一次磁盘I/O,将这个“头块”的内容(包含
N-1
个新的空闲块号和1个更下一组的头块地址)一次性地读入内存,完全覆盖并填满“当前可用栈”。 -
现在内存栈又满了,回到情况A,从新的栈顶弹出一个块号进行分配。
-
3. 回收空闲块时,如何使用内存栈?
当一个文件被删除,其占用的盘块被回收时:
-
检查内存栈: 系统首先查看“当前可用栈”是否已满。
-
情况A:栈未满(最常见的情况)
-
直接对内存栈执行入栈操作,将回收的盘块编号压入栈顶。
-
优势体现: 同样,这个过程也完全在内存中完成,高效迅速。
-
-
情况B:栈已满(需要与磁盘交互)
-
内存栈中的“临时退货区”已经堆满。
-
系统将当前内存栈中的全部
N
个空闲块编号,作为一整个新的“分组”,一次性地写入到刚刚回收的那个盘块中。 -
这样,这个被回收的盘块就成了一个新的“分组头块”,它现在记录了另外
N-1
个空闲块的信息以及一个(来自旧栈底的)指向下一组的指针。 -
最后,清空内存栈,只在其中放入这个新头块的编号,表示现在只有一个“大包裹”可用。
-