成组链接法
成组链接法是UNIX/Linux等大型文件系统采用的文件空间管理方法。
- 在UNIX/Linux系统中,将空闲块分成若干组,每100个空闲块为一组,每组的第一个空闲块登记了下一组空闲块的物理盘块号和空闲块总数。
- 如果一组的第一个空闲块号等于0,则有特殊的含义,意味着该组是最后一组,即无下一个空闲块。
- 平时整个链接信息保存于计算机系统磁盘上的系统区,系统启动以后,第一组的链接信息经缓冲区复制到内存专用块中。
文件卷的目录区会专门用一个磁盘块作为超级块,当操作系统启动时会将超级块读入内存。并且要保证内外存超级块一致。
超级块
- 内容:记录下一组一盘块的数目、以及其对应的索引。
- 也就是说超级块,它就是一个块,里面存放的是下一个空闲块分组的目录。
- 对于我们映射到的块分组的第一块,是一种类似于超级块的结构。存放下一分组的数目和地址。
- 如果索引块的第一个地址帧(先这样叫)是0或者-1(看设定),那么就是没有再分组了。
- 最后一层分组的盘块数是会少一块的,因为要用来存放结束标志
1、空闲盘块的组织
- 空闲盘块号栈:用来存放当前可用的一组空闲盘块的盘块号(最多含100 个号),以及栈中尚有的空闲盘块号数N。顺便指出,N 还兼作栈顶指针用。
- 例如,当N=100 时,它指向S.free(99)。由于栈是临界资源,每次只允许一个进程去访问,故系统为栈设置了一把锁。(只有这个是放在内存中的,其它是在磁盘上。)
- 文件区中的所有空闲盘块被分成若干个组,比如,将每100 个盘块作为一组。
- 假定盘上共有10 000 个盘块,每块大小为1 KB,其中第201~7999 号盘块用于存放文件,即作为文件区,这样,该区的最末一组盘块号应为7901~7999;次末组为7801~7900……;第二组的盘块号为301~400;第一组为201~300。
- 将每一组含有的盘块总数N 和该组所有的盘块号记入其前一组的第一个盘块的S.free(0)~S.free(99)中。这样,由各组的第一个盘块可链成一条链。
- 将第一组的盘块总数和所有的盘块号记入空闲盘块号栈中,作为当前可供分配的空闲盘块号。
- 最末一组只有99 个盘块,其盘块号分别记入其前一组的S.free(1) ~S.free(99)中,而在S.free(0)中则存放“0”,作为空闲盘块链的结束标志。
- (注:最后一组的盘块数应为99,不应是100,因为这是指可供使用的空闲盘块,其编号应为(1~99),0号中放空闲盘块链的结尾标志。)
2、空闲盘块的分配与回收
分配
当系统要为用户分配文件所需的盘块时,须调用盘块分配过程来完成。
- 该过程首先检查空闲盘块号栈是否上锁,如未上锁,便从栈顶取出一空闲盘块号,将与之对应的盘块分配给用户,然后将栈顶指针下移一格。
- 若该盘块号已是栈底,即S.free(0),这是当前栈中最后一个可分配的盘块号。
- 由于在该盘块号所对应的盘块中记有下一组可用的盘块号,因此,须调用磁盘读过程,将栈底盘块号所对应盘块的内容读入栈中,作为新的盘块号栈的内容,并把原栈底对应的盘块分配出去(其中的有用数据已读入栈中)。
- 然后,再分配一相应的缓冲区(作为该盘块的缓冲区)。最后,把栈中的空闲盘块数减1 并返回。
上面这个写得很乱,我们来详细整理一下基本的思路:
- 首先,对于我们目前而言的超级块,是一个块,块内的帧存的是存储数据的块的地址。
- 我们把这个连续分配的超级块看成一个静态的栈,用超级块存储的块数,来作为栈顶指针。
- 每一次分配磁盘块,就出栈一次(分配空闲块),出栈操作就是张丁减一,然后被空出来的位置的数据当作清零。
- 当空栈,那么就把下一级的索引块的内容复制进入超级块(那个索引块也会被当做空闲块分配掉)
回收
在系统回收空闲盘块时,须调用盘块回收过程进行回收。
- 它是将回收盘块的盘块号记入空闲盘块号栈的顶部,并执行空闲盘块数加1 操作。
- 当栈中空闲盘块号数目已达100 时,表示栈已满,便将现有栈中的100个盘块号记入新回收的盘块中,再将其盘块号作为新栈底。
简而言之,也就是我们的索引结构也是一个栈,这个栈的元素也是栈,当我们装载空闲块,是现在内存对应的超级块的栈满了,那就把现在超级块内的内容复制,作为下一级索引块,内存中超级块刷新。