OS之存储管理---详解文件系统的实现方式(一)

文件系统的结构

文件系统提供高效和便捷的磁盘访问,以便允许轻松存储、定位、提取数据。文件系统通常由不同的层组成,每层设计利用更低层的功能,创建新的功能,以用于更高层的服务。
在这里插入图片描述

  • I/O控制层包括设备驱动程序和中断处理程序,以在主内存和磁盘系统之间传输信息。
  • 基本文件系统只需要向适当设备驱动程序发送通用命令,以读取和写入磁盘的物理块。该层也管理内存缓冲区和保存各种文件系统、目录和数据块的缓存。
  • 文件组织模块知道文件和其逻辑块以及物理块,可以将逻辑块地址转成物理块地址,以供基本文件系统传输。文件组织模块还高阔可用空间管理器,以跟踪未分配的块并根据要求提供给文件组织模块。
  • 逻辑文件系统管理元数据信息。元数据包括文件系统的所有结构,而不包括实际数据。逻辑文件系统管理目录结构,以便根据给定文件名称为文件组织模块提供所需的信息。
文件系统可能包含的信息
  • 每个卷的引导控制块,可以包含改卷引导操作系统的所需信息,通常是卷的第一块,UFS称之为引导块;NTFS称之为分区引导扇区
  • 每个卷的卷控制块,包括卷(或分区)的详细信息,如分区的块的数量、块的大小、空闲块的数量和指针、空闲的FCB数量和FCB指针等。UFS称之为超级块,而在NTFS中存储在主控文件表中。
  • 每个文件系统的目录结构用于组织文件。在UFS中,它包含文件名和相关的inode的号码;在NTFS中它存储在主控文件表中。
  • 每个文件的FCB包括该文件的详细信息,有一个唯一标识码,以便和目录条目相关联。在NTFS中这些信息存储在主控文件表中,使用关系数据库结构,每个文件占一行。

内存中的信息用于管理文件系统并通过缓存来提高性能,这些数据在安装文件系统时被加载,在文件系统操作期间被更新,在卸载时被丢弃,这些结构类型可能包括:

  • 内存中的安装表包含每个安装卷的有关信息
  • 内存中的目录结构的缓存含有最近访问目录的信息
  • 整个系统的打开文件表包括每个打开文件表包括每个打开文件的FCB的副本以及其他其他信息。
  • 每个进程的打开文件表包括一个指向整个系统的打开文件表中的适当条目的指针,以及其他信息。
  • 当对磁盘读出或写入时,缓冲区保存文件系统的块

为了创建新的文件,应用程序调用逻辑文件系统,逻辑文件系统知道目录结构的格式,会分配一个新的FCB,系统将相应的目录读到内存,使用新的文件名和FCB进行更新,并将其写入到磁盘。
在这里插入图片描述
文件一旦被创立,就能用于I/O,但是前提是该文件已经被打开。系统调用open()将文件名传递到逻辑文件系统,系统调用open()首先搜索整个系统的打开文件表,如果打开,那么在单个进程的打开文件表中创建一个条目,并让其指向现有整个系统的打开文件表,如果这个文件尚未打开那么会根据给定的文件名来搜索目录结构。在找到文件后该文件的FCB会复制到内存的整个系统的开发文件表中,该表不但存储FCB,并且还跟踪打开该文件的进程的数量。接下来在单个进程的打开文件表中会创建一个条目,指向整个系统打开文件表的条目的一个指针,以及其他一些域。这些域可能包含文件的当前位置的指针和打开文件的访问模式。调用open()返回单个进程的打开文件表的适当条目的一个指针。
当文件关闭时,它的单个进程表的条目会被删除,并且整个系统的条目的打开数量会被递减。当所有打开该文件的用户关闭它时,任何更新的元数据会被复制到基于磁盘的目录结构,并且整个系统的打开文件表的条目被删除。

目录实现

线性列表

目录实现最简单的方式是采用文件名称和数据块指针的线性列表,这个方法编程简单但是执行费时。
目录条目的线性列表的缺点是,查找文件要线性搜索。使用这种实现的操作系统大多会采用软件缓存,以存储最近访问的目录信息。同时排序列表可以使用二分查找,减少平均搜索时间。
排序列表的优点是,不需要单独的排序步骤就可以生成排序的目录信息。

哈希表

这是熟知的一种方式,但是需要注意要做出规定来避免碰撞。还有一个困难就是,它的通常固定的大小和哈希函数对大小的依赖性。比如使用线性哈希表来存储64个条目,哈希函数可以将文件名称转换为0-63的整数,如果后来设法创建第65个文件,则必须扩大目录哈希表或者一个新的哈希函数来将文件映射。或者采用溢出策略的哈希表。

分配方法

磁盘空间的分配方法主要有三个:连续、链接和索引。

连续分配

连续分配要求每个文件在磁盘上占有一组连续的块,磁盘地址为磁盘定义了一个线性排序,有了这个排序,假设只有一个作业正在访问磁盘,在块b之后访问块b+1通常不需要移动磁头。当需要磁头移动(从一个柱面的最后扇区到下一个柱面的第一扇区)时,只需要移动一个磁道。文件的连续分配可以用首块的磁盘地址和连续的块数来定义,每个文件的目录条目包括起始块的地址和该文件所分配的区域的长度。综上啊,连续分配支持顺序访问和直接访问。
但是在采用连续分配为新文件找空间时需要找到合适的空间大小,可以采用首次适应或最优适应算法进行寻找。
连续分配的问题

  • 会有外部碎片,这是不能避免的问题,解决方法就是将这个文件系统复制到另一个磁盘,原来的磁盘完全变成空的,从而创建了一个大的连续空间。然后通过从这个大的连续空闲空间采用连续分配方法,将这些文件复制回来,但是代价是时间消耗很大。
  • 如何确定一个文件需要多少空间也是一个问题,因为如果文件分配的空间太小,那么可能文件就无法扩展,如果太大,又会造成空间的浪费。有些操作系统使用连续分配的修正方案:最初分配一块连续空间,当这个数量不够时会添加另一块连续空间(称为扩展),然后文件块的位置就记录为:地址、块数、下一扩展的首块的指针。
链接分配

链接分配解决了连续分配的所有问题,如果使用链接分配,每个文件是磁盘块的链表,磁盘块可能会散布在磁盘的任何地方。要创建新的文件只需要在目录中增加一个条目,采用链接分配每个目录条目都有文件首个磁盘块的一个指针,读文件时,只需要按照到块的指针来读块。

链接分配存在缺点:

  • 只能够有效用于顺序访问文件,链接分配不能有效支持文件的直接访问。
  • 另一个问题是指针所需要的空间,比如指针需要使用512字节块的4字节,则0.78%的磁盘空间会用于指针,每个文件需要比原来稍多的空间。
    这个问题通常通过将多个块组成并按照簇而不是块来分配。比如在文件系统上定义一个簇为4块,在磁盘上仅以簇为单位来操作。这样指针所占用的磁盘空间的百分比就小得多,但是这种方式的代价就是增加了内部碎片。
  • 可靠性。因为文件是通过散布在磁盘上的指针链接的,如果指针丢失或损坏将会发生什么呢??现在有些不完全的解决方案就是采用双向链表;或者是每块存储文件名称和相对块号,但是这些方法都会为每个文件增加更多的额外开销。
文件分配表(FAT)

文件分配表是链接分配的一个变种,用于MS-DOS操作系统。每个卷的开头部分的磁盘用于存储该表。在该表中,每个磁盘块都有一个条目,并可按块号来进行索。FAT的使用与链表相同,目录条目包含文件首块的块号,通过这个块号索引的表条目包含文件的下一块块号,这条链会继续下去,直到最后一块。而最后一块的表条目的值为文件结束值。为文件分配一个新块只要简单找到第一个值为0的FAT条目,用新块的地址替换前面文件结束值。
在这里插入图片描述
如果不对FAT采用缓存,FAT分配方案可能会导致大量的磁头寻道时间。磁头必须移到卷的开头,读入FAT,找到所需的块的位置,在移动到块本身的位置,在最坏的情况下,每块都需要移动两次。优点是改善了随机访问时间;因为通过读入FAT信息,磁头能找到任何块的位置。

索引分配

顾名思义就是通过将所有指针放在一起,即索引块,解决了链接分配不能直接访问块的问题。
每个文件都有自己的索引块,这是一个磁盘块地址的数组。索引块的第i个条目指向文件的第i块。目录包含索引快的地址。当查找和读取第i个块时,采用第i个索引块条目的指针。
当创建文件时,索引块的所有指针都设为null。当首次写入第i块时,先从空闲空间管理器这种获得一块,再将其地址写到索引块的第i个条目。
索引分配的问题:索引分配很浪费空间,因为索引块指针的开销通常大于链接分配的指针开销。比如,就算只有一个两个指针是非空的,也需要分配一个完整的索引块。

那么索引块应该怎样分配呢??有如下几种方案:

  • 链接方案:一个索引块通常为一个磁盘块。为了支持大的文件,可以将多个索引块链接起来。
  • 多级索引:通过第一级索引块指向一组第二级的索引块,它又指向文件块。当访问一块时,操作系统通过第一级索引查找第二级索引块,在采用这个块查找所需的数据。
  • 组合方案:在基于UNIX的文件系统中,将索引块的前几个指针存在文件的inode中,这些指针的前12个指向直接块,即他们包含存储文件数据的块的地址。接下来的3个指针指向间接块。第一个指向一级间接块,一级间接块为索引快,包含的是真正包含数据的块的地址;第二个指向二级间接块,二级间接块包含一个块的地址,而这个块内的地址指向了一些块,这些块中包含了指向真实数据块的指针;最后一个为三级间接块指针。

采用这种方法一个文件的块数可以超过许多操作系统所用的4字节的文件指针所能访问的空间。32位指针能访问 2 32 2^{32} 232字节,或4GB。

空闲空间管理

为了跟踪空闲磁盘空间,系统需要维护一个空闲空间列表。空闲空间列表记录了所有空闲磁盘空间,即未分配给文件或目录的空间,注意,空闲空间列表虽然称为列表但是不一定按照列表来实现。

位向量

空闲空间列表按位图或位向量来实现。每块用一个位来表示,如果块是空闲的,位为1;如果块是分配的,位为0。
例如假设一个磁盘,其中块2,34,5,8,9,10,11,12,13,17,18,25,26,27为空闲的,而其他块是分配的,那么空闲空间的位图是:

001111001111110001100000011100000…

这种方法的优点是,在查找磁盘上的第一个空闲块和n个连续空闲块时相对简单和高效。
每一块的块号码计算如下:

(每个字的位数) * (值为0的字数) + 第一个值为1的位的偏移

链表

将所有空闲磁盘块用链表链接起来,将指向第一空闲块的指针保存在磁盘的特殊位置,同时也将缓存卸载内存中。这种方法称为空闲链表。但是这种方法比较低效,在遍历整个列表时,需要读入每块,从而需要大量的I/O时间。

在第一个空闲块中存储n个空闲块的地址。这些块的前n-1个确实是空的,最后一块包含另外n个空闲块的地址,如此继续,大量空闲块的地址可以很快的找到,这一点有别于标准链表方法。

计数

通常,多个连续块可能需要同时分配或者释放,尤其是采用连续区域分配算法或采用簇来分配空间更是如此,因此不是记录n个空闲块的磁盘地址,而是记录第一块的地址和紧跟第一块的连续空闲块的数量n。这样,空闲空间列表的每个条目包含磁盘地址和数量。
注意:这种跟踪空闲空间的方法类似于分配块的扩展方法,这些条目可以存储在平衡树而不是链表中,以便高校查找插入和删除。

参见于:《操作系统概念
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值