文件管理======

Posted dearQiHao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件管理======相关的知识,希望对你有一定的参考价值。


  在现代计算机系统中,要用到大量的程序和数据,因内存容量有限,且不能长期保存, 故而平时总是把它们以文件的形式存放在外存中,需要时再随时将它们调入内存。如果由用户直接管理外存上的文件,不仅要求用户熟悉外存特性,了解各种文件的属性,以及它 们在外存上的位置,而且在多用户环境下,还必须能保持数据的安全性和一致性。显然, 这是用户所不能胜任、也不愿意承担的工作。于是,取而代之的便是在操作系统中又增加 了文件管理功能,即构成一个文件系统,负责管理在外存上的文件,并把对文件的存取、 共享和保护等手段提供给用户。这不仅方便了用户,保证了文件的安全性,还可有效地提 高系统资源的利用率。

6.1 文件和文件系统

  在现代 OS 中,几乎毫无例外地是通过文件系统来组织和管理在计算机中所存储的大量程序和数据的;或者说,文件系统的管理功能,是通过把它所管理的程序和数据组织成一 系列文件的方法来实现的。而文件则是指具有文件名的若干相关元素的集合。元素通常是记录,而记录又是一组有意义的数据项的集合。可见,基于文件系统的概念,可以把数据组成分为数据项、记录和文件三级。

6.1.1 文件、记录和数据项

  1. 数据项

  (1) 基本数据项。这是用于描述一个对象的某种属性的字符集,是数据组织中可以命名 的最小逻辑数据单位,即原子数据,又称为数据元素或字段。它的命名往往与其属性一致。 例如,用于描述一个学生的基本数据项有学号、姓名、年龄、所在班级等。
  (2) 组合数据项。它是由若干个基本数据项组成的,简称组项。例如,经理便是个组项, 它由正经理和副经理两个基本项组成。又如,工资也是个组项,它可由基本工资、工龄工 资和奖励工资等基本项所组成。
  基本数据项除了数据名外,还应有数据类型。因为基本项仅是描述某个对象的属性, 根据属性的不同,需要用不同的数据类型来描述。例如,在描述学生的学号时,应使用整 数;描述学生的姓名则应使用字符串(含汉字);描述性别时,可用逻辑变量或汉字。可见, 由数据项的名字和类型两者共同定义了一个数据项的“型”。而表征一个实体在数据项上的 数据则称为“值”。例如,学号/30211、姓名/王有年、性别/男等。

  1. 记录

  记录是一组相关数据项的集合,用于描述一个对象在某方面的属性。一个记录应包含 哪些数据项,取决于需要描述对象的哪个方面。而一个对象,由于他所处的环境不同可把 他作为不同的对象。例如,一个学生,当把他作为班上的一名学生时,对他的描述应使用 学号、姓名、年龄及所在系班,也可能还包括他所学过的课程的名称、成绩等数据项。但 若把学生作为一个医疗对象时,对他描述的数据项则应使用诸如病历号、姓名、性别、出 生年月、身高、体重、血压及病史等项。
  在诸多记录中,为了能惟一地标识一个记录,必须在一个记录的各个数据项中,确定 出一个或几个数据项,把它们的集合称为关键字(key)。或者说,关键字是惟一能标识一个 记录的数据项。通常,只需用一个数据项作为关键字。例如,前面的病历号或学号便可用 来从诸多记录中标识出惟一的一个记录。然而有时找不到这样的数据项,只好把几个数据 项定为能在诸多记录中惟一地标识出某个记录的关键字。

  1. 文件

  文件是指由创建者所定义的、具有文件名的一组相关元素的集合,可分为有结构文件 和无结构文件两种。在有结构的文件中,文件由若干个相关记录组成;而无结构文件则被 看成是一个字符流。文件在文件系统中是一个最大的数据单位,它描述了一个对象集。例 如,可以将一个班的学生记录作为一个文件。一个文件必须要有一个文件名,它通常是由 一串 ASCII 码或(和)汉字构成的,名字的长度因系统不同而异。如在有的系统中把名字规定 为 8 个字符,而在有的系统中又规定可用 14 个字符。用户利用文件名来访问文件。
  此外,文件应具有自己的属性,属性可以包括:
    (1) 文件类型。可以从不同的角 度来规定文件的类型,如源文件、目标文件及可执行文 件等。
    (2) 文件长度。文件长度指文件的当前长度,长度的单位可以是字节、字或块,也可能 是最大允许的长度。
    (3) 文件的物理位置。该项属性通常是用于指示文件在哪一个设备上及在该设备的哪个 位置的指针。
    (4) 文件的建立时间。这是指文件最后一次的修改时间等。 图 6-1 示出了文件、记录和数据项之间的层次关系。

6.1.2 文件类型和文件系统模型

  1. 文件类型
    1)按用途分类

  (1) 系统文件。这是指由系统软件构成的文件。大多数的系统文件只允许用户调用,但 不允许用户去读,更不允许修改;有的系统文件不直接对用户开放。
  (2) 用户文件。指由用户的源代码、目标文件、可执行文件或数据等所构成的文件。用 户将这些文件委托给系统保管。
  (3) 库文件。这是由标准子例程及常用的例程等所构成的文件。这类文件允许用户调用, 但不允许修改。

 2)按文件中数据的形式分类

  (1) 源文件。这是指由源程序和数据构成的文件。通常由终端或输入设备输入的源程序 和数据所形成的文件都属于源文件。它通常是由 ASCII 码或汉字所组成的。
  (2) 目标文件。这是指把源程序经过相应语言的编译程序编译过,但尚未经过链接程序 链接的目标代码所构成的文件。它属于二进制文件。 通常,目标文件所使用的后缀名是 “.obj”。
  (3) 可执行文件。这是指把编译后所产生的目标代码再经过链接程序链接后所形成的 文件。

 3)按存取控制属性分类

  (1) 只执行文件。该类文件只允许被核准的用户调用执行,既不允许读,更不允许写。
  (2) 只读文件。该类文件只允许文件主及被核准的用户去读,但不允许写。
  (3) 读写文件。这是指允许文件主和被核准的用户去读或写的文件。
  4) 按组织形式和处理方式分类

根据文件的组织形式和系统对其的处理方式,可将文件分为三类:

  (1) 普通文件:由 ASCII 码或二进制码组成的字符文件。一般用户建立的源程序文件、 数据文件、目标代码文件及操作系统自身代码文件、库文件、实用程序文件等都是普通文 件,它们通常存储在外存储设备上。
  (2) 目录文件:由文件目录组成的,用来管理和实现文件系统功能的系统文件,通过目 录文件可以对其它文件的信息进行检索。由于目录文件也是由字符序列构成,因此对其可 进行与普通文件一样的种种文件操作。
  (3) 特殊文件:特指系统中的各类 I/O 设备。 为了便于统一管理, 系统将所有的输入/输出设备都视为文件,按文件方式提供给用户使用,如目录的检索、权限的验证等都 与普通文件相似,只是对这些文件的操作是和设备驱动程序紧密相连的,系统将这些操作 转为对具体设备的操作。根据设备数据交换单位的不同,又可将特殊文件分为块设备文件 和字符设备文件。前者用于磁盘、光盘或磁带等块设备的 I/O 操作,而后者用于终端、打 印机等字符设备的 I/O 操作。

  1. 文件系统模型

  图 6-2 示出了文件系统的模型。可将该模型分为三个层次,其最底层是对象及其属性; 中间层是对对象进行操纵和管理的软件集合;最高层是文件系统提供给用户的接口。

  1) 对象及其属性
  文件管理系统管理的对象有:
    ① 文件。它作为文件管理的直接对象。
    ② 目录。为了 方便用户对文件的存取和检索,在文件系统中必须配置目录,每个目录项中,必须含有文 件名及该文件所在的物理地址(或指针)。对目录的组织和管理是方便用户和提高对文件存取 速度的关键。
    ③ 磁盘(磁带)存储空间。文件和目录必定占用存储空间,对这部分空间的有 效管理,不仅能提高外存的利用率,而且能提高对文件的存取速度。
  2) 对对象操纵和管理的软件集合
  这是文件管理系统的核心部分。文件系统的功能大多是在这一层实现的,其中包括: 对文件存储空间的管理、对文件目录的管理、用于将文件的逻辑地址转换为物理地址的机制、 对文件读和写的管理,以及对文件的共享与保护等功能。
  3) 文件系统的接口
  为方便用户使用文件系统,文件系统通常向用户提供两种类型的接口:
  (1) 命令接口。 这是指作为用户与文件系统交互的接口。 用户可通过键盘终端键入命 令,取得文件系统的服务。
  (2) 程序接口。这是指作为用户程序与文件系统的接口。用户程序可通过系统调用来取 得文件系统的服务。

6.1.3 文件操作

  1. 最基本的文件操作

  (1) 创建文件。在创建一个新文件时,系统首先要为新文件分配必要的外存空间,并在 文件系统的目录中,为之建立一个目录项。目录项中应记录新文件的文件名及其在外存的 地址等属性。
  (2) 删除文件。当已不再需要某文件时,可将它从文件系统中删除。在删除时,系统应 先从目录中找到要删除文件的目录项,使之成为空项,然后回收该文件所占用的存储空间。
  (3) 读文件。在读一个文件时,须在相应系统调用中给出文件名和应读入的内存目标地 址。此时,系统同样要查找目录,找到指定的目录项,从中得到被读文件在外存中的位置。 在目录项中,还有一个指针用于对文件的读/写。
  (4) 写文件。在写一个文件时,须在相应系统调用中给出该文件名及该文件在内存中的 (源)地址。为此,也同样须先查找目录,找到指定文件的目录项,再利用目录中的写指针进 行写操作。
  (5) 截断文件。如果一个文件的内容已经陈旧而需要全部更新时,一种方法是将此文件 删除,再重新创建一个新文件。但如果文件名及其属性均无改变时,则可采取另一种所谓的截 断文件的方法,此即将原有文件的长度设置为 0,或者说是放弃原有的文件内容。
  (6) 设置文件的读/写位置。前述的文件读/写操作都只提供了对文件顺序存取的手段, 即每次都是从文件的始端读或写。设置文件读/写位置的操作,用于设置文件读/写指针的位 置,以便每次读/写文件时,不是从其始端而是从所设置的位置开始操作。也正因如此,才 能改顺序存取为随机存取。

  1. 文件的“打开”和“关闭”操作

  当前 OS 所提供的大多数对文件的操作,其过程大致都是这样两步: 第一步是通过检索文 件目录来找到指定文件的属性及其在外存上的位置;第二步是对文件实施相应的操作,如读 文件或写文件等。当用户要求对一个文件实施多次读/写或其它操作时,每次都要从检索目录 开始。为了避免多次重复地检索目录,在大多数 OS 中都引入了“打开”(open)这一文件系统 调用,当用户第一次请求对某文件进行操作时,先利用 open 系统调用将该文件打开。
   所谓“打开”,是指系统将指名文件的属性(包括该文件在外存上的物理位置)从外存拷 贝到内存打开文件表的一个表目中,并将该表目的编号(或称为索引)返回给用户。以后,当 用户再要求对该文件进行相应的操作时,便可利用系统所返回的索引号向系统提出操作请 求。系统这时便可直接利用该索引号到打开文件表中去查找,从而避免了对该文件的再次 检索。这样不仅节省了大量的检索开销,也显著地提高了对文件的操作速度。如果用户已 不再需要对该文件实施相应的操作时,可利用“关闭”(close)系统调用来关闭此文件,OS 将会把该文件从打开文件表中的表目上删除掉。

  1. 其他文件操作

   为了方便用户使用文件,通常,OS 都提供了数条有关文件操作的系统调用,可将这些 调用分成若干类: 最常用的一类是有关对文件属性进行操作的,即允许用户直接设置和获得 文件的属性,如改变已存文件的文件名、改变文件的拥有者(文件主)、改变对文件的访问权, 以及查询文件的状态(包括文件类型、大小和拥有者以及对文件的访问权等);另一类是有关 目录的,如创建一个目录,删除一个目录,改变当前目录和工作目录等;此外,还有用于实现文件共享的系统调用和用于对文件系统进行操作的系统调用等。
   值得说明的是,有许多文件操作都可以利用上述基本操作加以组合来实现。例如,创 建一个文件拷贝的操作,可利用两条基本操作来实现。其第一步是利用创建文件的系统调 用来创建一个新文件;第二步是将原有文件中的内容写入新文件中。

6.2 文件的逻辑结构

通常,文件是由一系列的记录组成的。文件系统设计的关键要素,是指将这些记录构 成一个文件的方法,以及将一个文件存储到外存上的方法。事实上,对于任何一个文件, 都存在着以下两种形式的结构:

  (1) 文件的逻辑结构(File Logical Structure)。这是从用户观点出发所观察到的文件组织 形式,是用户可以直接处理的数据及其结构,它独立于文件的物理特性,又称为文件组织(File Organization)。
  (2) 文件的物理结构,又称为文件的存储结构,是指文件在外存上的存储组织形式。这不仅与存储介质的存储性能有关,而且与所采用的外存分配方式有关。 无论是文件的逻辑结构,还是其物理结构,都会影响对文件的检索速度。本节只介绍 文件的逻辑结构。 对文件逻辑结构所提出的基本要求,首先是能提高检索速度,即在将大批记录组成文 件时,应有利于提高检索记录的速度和效率;其次是便于修改,即便于在文件中增加、删 除和修改一个或多个记录;第三是降低文件的存储费用,即减少文件占用的存储空间,不要求大片的连续存储空间。

6.2.1 文件逻辑结构的类型

  1. 有结构文件

  (1) 定长记录。这是指文件中所有记录的长度都是相同的,所有记录中的各数据项都处 在记录中相同的位置,具有相同的顺序和长度。文件的长度用记录数目表示。对定长记录 的处理方便、开销小,所以这是目前较常用的一种记录格式,被广泛用于数据处理中。
  (2) 变长记录。这是指文件中各记录的长度不相同。产生变长记录的原因,可能是由于 一个记录中所包含的数据项数目并不相同,如书的著作者、论文中的关键词等;也可能是 数据项本身的长度不定,例如,病历记录中的病因、病史;科技情报记录中的摘要等。不 论是哪一种,在处理前,每个记录的长度是可知的。 根据用户和系统管理上的需要, 可采用多种方式来组织这些记录,形成下述的几种 文件:
    (1) 顺序文件。这是由一系列记录按某种顺序排列所形成的文件。其中的记录通常是定 长记录,因而能用较快的速度查找文件中的记录。
    (2) 索引文件。当记录为可变长度时,通常为之建立一张索引表,并为每个记录设置一 个表项,以加快对记录检索的速度。
    (3) 索引顺序文件。这是上述两种文件构成方式的结合。它为文件建立一张索引表,为 每一组记录中的第一个记录设置一个表项。

  1. 无结构文件
      如果说大量的数据结构和数据库是采用有结构的文件形式的话,则大量的源程序、可 执行文件、库函数等,所采用的就是无结构的文件形式,即流式文件。其长度以字节为单 位。对流式文件的访问,则是采用读/写指针来指出下一个要访问的字符。可以把流式文件 看做是记录式文件的一个特例。在 UNIX 系统中,所有的文件都被看做是流式文件,即使 是有结构文件,也被视为流式文件,系统不对文件进行格式处理。

6.2.2 顺序文件

  1. 逻辑记录的排列

  文件是记录的集合。文件中的记录可以是任意顺序的,因此,它可以按照各种不同的 顺序进行排列。一般地,可归纳为以下两种情况:
    第一种是串结构,各记录之间的顺序与关键字无关。通常的办法是由时间来决定,即 按存入时间的先后排列,最先存入的记录作为第一个记录,其次存入的为第二个记录……, 依此类推。
    第二种情况是顺序结构,指文件中的所有记录按关键字(词)排列。可以按关键词的长短 从小到大排序,也可以从大到小排序;或按其英文字母顺序排序。
  对顺序结构文件可有更高的检索效率,因为在检索串结构文件时,每次都必须从头开 始,逐个记录地查找,直至找到指定的记录,或查完所有的记录为止。而对顺序结构文件, 则可利用某种有效的查找算法,如折半查找法、插值查找法、跳步查找法等方法来提高检 索效率。

  1. 对顺序文件的 读/写操作

  顺序文件中的记录可以是定长的,也可以是变长的。 对于定长记录的顺序文件,如 果已知当前记录的逻辑地址,便很容易确定下一个记录的逻辑地址。 在读一个文件时, 可设置一个读指针 Rptr, 令它指向下一个记录的首地址, 每当读完一个记录时, 便 执行
  Rptr:=Rptr + L 操作,使之指向下一个记录的首地址,其中的 L 为记录长度。类似地,在写一个文件时, 也应设置一个写指针 Wptr,使之指向要写的记录的首地址。同样,在每写完一个记录时, 又须执行以下操作:
  Wptr:=Wptr + L
  对于变长记录的顺序文件,在顺序读或写时的情况相似,但应分别为它们设置读或写指针,在每次读或写完一个记录后,须将读或写指针加上 Li 。L i 是刚读或刚写完的记录的 长度。图 6-3 所示为定长和变长记录文件。

  1. 顺序文件的优缺点

  顺序文件的最佳应用场合是在对诸记录进行批量存取时,即每次要读或写一大批记录 时。此时,对顺序文件的存取效率是所有逻辑文件中最高的;此外,也只有顺序文件才能 存储在磁带上,并能有效地工作。
  在交互应用的场合,如果用户(程序)要求查找或修改单个记录,为此系统便要去逐个地 查找诸记录。这时,顺序文件所表现出来的性能就可能很差,尤其是当文件较大时,情况 更为严重。例如,有一个含有 10 4 个记录的顺序文件,如果对它采用顺序查找法去查找一个 指定的记录,则平均需要查找 5×10 3 个记录;如果是可变长记录的顺序文件,则为查找一 个记录所需付出的开销将更大,这就限制了顺序文件的长度。
  顺序文件的另一个缺点是,如果想增加或删除一个记录都比较困难。为了解决这一问 题, 可以为顺序文件配置一个运行记录文件(Log File),或称为事务文件(Transaction File), 把试图增加、删除或修改的信息记录于其中,规定每隔一定时间,例如 4 小时,将运行记 录文件与原来的主文件加以合并,产生一个按关键字排序的新文件。

6.2.3 索引文件

  对于定长记录文件,如果要查找第 i 个记录,可直接根据下式计算来获得第 i 个记录相 对于第一个记录首址的地址:
  A i = i × L
  然而,对于可变长度记录的文件,要查找其第 i 个记录时,须首先计算出该记录的首地 址。为此,须顺序地查找每个记录,从中获得相应记录的长度 Li ,然后才能按下式计算出 第 i 个记录的首址。假定在每个记录前用一个字节指明该记录的长度,则
  可见,对于定长记录,除了可以方便地实现顺序存取外,还可较方便地实现直接存取。 然而,对于变长记录就较难实现直接存取了,因为用直接存取方法来访问变长记录文件中 的一个记录是十分低效的,其检索时间也很难令人接受。为了解决这一问题,可为变长记 录文件建立一张索引表,对主文件中的每个记录,在索引表中设有一个相应的表项,用于 记录该记录的长度 L 及指向该记录的指针(指向该记录在逻辑地址空间的首址)。由于索引表 是按记录键排序的,因此,索引表本身是一个定长记录的顺序文件,从而也就可以方便地 实现直接存取。图 6-4 示出了索引文件(Index File)的组织形式。

  在对索引文件进行检索时,首先是根据用户(程序)提供的关键字,并利用折半查找法去 检索索引表,从中找到相应的表项;再利用该表项中给出的指向记录的指针值,去访问所 需的记录。而每当要向索引文件中增加一个新记录时,便须对索引表进行修改。由于索引 文件可有较快的检索速度,故它主要用于对信息处理的及时性要求较高的场合,使用索引文件的主要问题是,它除了有主文件外,还须配置一张索引表,而 且每个记录都要有一个索引项,因此提高了存储费用。

6.2.4 索引顺序文件

  索引顺序文件可能是最常见的一种逻辑文件形式。它有效地克服了变长记录文件不便于直接存取的缺点,而且所付出的代价也不算太大。前已述及,它是顺序文件和索引文件相结合的产物。它将顺序文件中的所有记录分为若干个组(例如,50 个 记录为一个组);为顺序文件建立一张索引表,在索引表中为每组中的第一个记录建立一个 索引项,其中含有该记录的键值和指向该记录的指针。索引顺序文件如图 6-5 所示。
  在对索引顺序文件进行检索时,首先也是利用用户(程序)所提供的关键字以及某种查 找算法去检索索引表,找到该记录所在记录组中第一个记录的表项,从中得到该记录组第 一个记录在主文件中的位置;然后,再利用顺序查找法去查找主文件,从中找到所要求的 记录。
  如果在一个顺序文件中所含有的记录数为 N,则为检索到具有指定关键字的记录,平均 须查找 N/2 个记录;但对于索引顺序文件,则为能检索到具有指定关键字的记录,平均只 要查找 N 个记录数,因而其检索效率 S 比顺序文件约提高 N /2 倍。例如,有一个顺序 文件含有 10 000 个记录,平均须查找的记录数为 5000 个。但对于索引顺序文件,则平均只 须查找 100 个记录。可见,它的检索效率是顺序文件的 50 倍。
  但对于一个非常大的文件,为找到一个记录而须查找的记录数目仍然很多,例如,对 于一个含有 10 6 个记录的顺序文件,当把它作为索引顺序文件时,为找到一个记录,平均须 查找 1000 个记录。为了进一步提高检索效率,可以为顺序文件建立多级索引,即为索引文 件再建立一张索引表,从而形成两级索引表。例如,对于一个含有 10 6 个记录的顺序文件, 可先为该文件建立一张低级索引表,每 100 个记录为一组,故低级索引表应含有 10 4 个表项, 而每个表项中存放顺序文件中每个组第一个记录的记录键值和指向该记录的指针,然后再 为低级索引表建立一张高级索引表。这时,也同样是每 100 个索引表项为一组,故具有 102 个表项。这里的每个表项中存放的是低级索引表每组第一个表项中的关键字和指向该表项 的指针。此时,为找到一个具有指定关键字的记录,所须查找的记录数平均为 50+50+50=150, 或者可表示为(3/2) 3 N 。其中,N 是顺序文件中记录的个数。注意,在未建立索引文件时所 需查找的记录数平均为 50 万个;对于建立了一级索引的顺序索引文件,平均需查找 1000 次;建立两级索引的顺序索引文件,平均只需查找 150 次。

6.5.2 直接文件和哈希文件

  1. 直接文件
      采用前述几种文件结构对记录进行存取时,都须利用给定的记录键值,先对线性表或 链表进行检索,以找到指定记录的物理地址。然而对于直接文件,则可根据给定的记录键 值,直接获得指定记录的物理地址。换言之,记录键值本身就决定了记录的物理地址。这 种由记录键值到记录物理地址的转换被称为键值转换(Key to address transformation)。组织直 接文件的关键,在于用什么方法进行从记录值到物理地址的转换。

  2. 哈希文件

  这是目前应用最为广泛的一种直接文件。它利用 Hash 函数(或称散列函数),可将记录 键值转换为相应记录的地址。但为了能实现文件存储空间的动态分配,通常由 Hash 函数所 求得的并非是相应记录的地址,而是指向一目录表相应表目的指针,该表目的内容指向相 应记录所在的物理块,如图 6-6 所示。例如,若令 K 为记录键值,用 A 作为通过 Hash 函数 H 的转换所形成的该记录在目录表中对应表目的位置,则有关系 A=H(K)。通常,把 Hash 函数作为标准函数存于系统中,供存取文件时调用。

6.3 外存分配方式

6.3.1 连续分配

  1. 连续分配方式

  连续分配要求为每一个文件分配一组相邻接的盘块。一组盘块的 地址定义了磁盘上的一段线性地址。例如,第一个盘块的地址为 b,则第二个盘块的地址为 b+1,第三个盘块的地址为 b+2……。通常,它们都位于一条磁道上,在进行读/写时,不必 移动磁头,仅当访问到一条磁道的最后一个盘块后,才需要移到下一条磁道,于是又去连 续地读/写多个盘块。在采用连续分配方式时,可把逻辑文件中的记录顺序地存储到邻接的 各物理盘块中,这样所形成的文件结构称为顺序文件结构,此时的物理文件称为顺序文件。 这种分配方式保证了逻辑文件中的记录顺序与存储器中文件占用盘块的顺序的一致性。为 使系统能找到文件存放的地址,应在目录项的“文件物理地址”字段中,记录该文件第一 个记录所在的盘块号和文件长度(以盘块数进行计量)。图 6-7 示出了连续分配的情况。图中 假定了记录与盘块的大小相同。Count 文件的第一个盘块号是 0,文件长度为 2,因此是在 盘块号为 0 和 1 的两盘块中存放文件 1 的数据。
如同内存的动态分区分配一样,随着文件建立时空间的分配和文件删除时空间的回收, 将使磁盘空间被分割成许多小块,这些较小的连续区已难于用来存储文件,此即外存的碎 片。同样,我们也可以利用紧凑的方法,将盘上所有的文件紧靠在一起,把所有的碎片拼 接成一大片连续的存储空间。例如,可以运行一个再装配例程(repack routine),由它将磁盘 A 上的大量文件拷贝到一张软盘 B 或几张软盘(C,D,…)上,并释放原来的 A 盘,使之成 为一个空闲盘。然后再将软盘 B(C,D,…)上的文件拷回 A 盘上。这种方法能将含有多个 文件的盘上的所有空闲盘块都集中在一起,从而消除了外部碎片。但为了将外存上的空闲 空间进行一次紧凑,所花费的时间远比将内存紧凑一次所花费的时间多得多。

  1. 连续分配的主要优缺点
    连续分配的主要优点如下:

  (1) 顺序访问容易。访问一个占有连续空间的文件非常容易。系统可从目录中找到该顺 序文件所在的第一个盘块号,从此开始顺序地、逐个盘块地往下读/写。连续分配也支持直 接存取。例如,要访问一个从 b 块开始存放的文件中的第 i 个盘块的内容,就可直接访问 b+i 号盘块。
  (2) 顺序访问速度快。因为由连续分配所装入的文件,其所占用的盘块可能是位于一条 或几条相邻的磁道上,这时,磁头的移动距离最少,因此,这种对文件访问的速度是几种 存储空间分配方式中最高的一种。

连续分配的主要缺点如下:

  (1) 要求有连续的存储空间。要为每一个文件分配一段连续的存储空间,这样,便会产 生出许多外部碎片,严重地降低了外存空间的利用率。如果是定期地利用紧凑方法来消除 碎片,则又需花费大量的机器时间。
  (2) 必须事先知道文件的长度。要将一个文件装入一个连续的存储区中,必须事先知道 文件的大小,然后根据其大小,在存储空间中找出一块其大小足够的存储区,将文件装入。 在有些情况下,知道文件的大小是件非常容易的事,如可拷贝一个已存文件。但有时却很 难,在此情况下,只能靠估算。如果估计的文件大小比实际文件小,就可能因存储空间不足而中止文件的拷贝,须再要求用户重新估算,然后再次执行。这样,显然既费时又麻烦。 这就促使用户往往将文件长度估得比实际的大,甚至使所计算的文件长度比实际长度大得 多,显然,这会严重地浪费外存空间。对于那些动态增长的文件,由于开始时文件很小, 在运行中逐渐增大,比如,这种增长要经历几天、几个月。在此情况下,即使事先知道文 件的最终大小,在采用预分配存储空间的方法时,显然也将是很低效的,即它使大量的存 储空间长期地空闲着。

6.3.2 链接分配

  1. 隐式链接

  在采用隐式链接分配方式时,在文件目录的每个目录项中,都须含有指向链接文件第 一个盘块和最后一个盘块的指针。图 6-8 中示出了一个占用 5 个盘块的链接式文件。在相 应的目录项中,指示了其第一个盘块号是 9,最后一个盘块号是 25。而在每个盘块中都含 有一个指向下一个盘块的指针,如在第一个盘块 9 中设置了第二个盘块的盘块号是 16;在 16 号盘块中又设置了第三个盘块的盘块号 1。如果指针占用 4 个字节,对于盘块大小为 512 字节的磁盘,则每个盘块中只有 508 个字节可供用户使用。
  隐式链接分配方式的主要问题在于:它只适合于顺序访问,它对随机访问是极其低效 的。如果要访问文件所在的第 i 个盘块,则必须先读出文件的第一个盘块……,就这样顺序 地查找直至第 i 块。当 i=100 时,须启动 100 次磁盘去实现读盘块的操作,平均每次都要花 费几十毫秒。可见,随机访问的速度相当低。此外,只通过链接指针来将一大批离散的盘 块链接起来,其可靠性较差,因为只要其中的任何一个指针出现问题,都会导致整个链的 断开。
  为了提高检索速度和减小指针所占用的存储空间,可以将几个盘块组成一个簇(cluster)。 比如,一个簇可包含 4 个盘块,在进行盘块分配时,是以簇为单位进行的。在链接文件中 的每个元素也是以簇为单位的。这样将会成倍地减小查找指定块的时间,而且也可减小指 针所占用的存储空间,但却增大了内部碎片,而且这种改进也是非常有限的。

  1. 显示链接

  这是指把用于链接文件各物理块的指针,显式地存放在内存的一张链接表中。该表在 整个磁盘仅设置一张,如图 6-9 所示。表的序号是物理盘块号,从 0 开始,直至 N-1;N 为 盘块总数。在每个表项中存放链接指针,即下一个盘块号。在该表中,凡是属于某一文件 的第一个盘块号,或者说是每一条链的链首指针所对应的盘块号,均作为文件地址被填入 相应文件的 FCB 的“物理地址”字段中。由于查找记录的过程是在内存中进行的,因而不 仅显著地提高了检索速度,而且大大减少了访问磁盘的次数。由于分配给文件的所有盘块 号都放在该表中,故把该表称为文件分配表 FAT(File Allocation Table)。

6.3.3 FAT 和 NTFS 技术

1.FAT12

  1) 以盘块为基本分配单位
  早期 MS-DOS 操作系统所使用的是 FAT12 文件系统,在每个分区中都配有两张文件分 配表 FAT1 和 FAT2,在 FAT 的每个表项中存放下一个盘块号,它实际上是用于盘块之间的 链接的指针,通过它可以将一个文件的所有的盘块链接起来,而将文件的第一个盘块号放 在自己的 FCB 中。图 6-10 示出了 MS-DOS 的文件物理结构,这里示出了两个文件,文件 A 占用三个盘块,其盘块号依次为 4、6、11;文件 B 则依次占用 9、10 及 5 号三个盘块。 每个文件的第一个盘块号放在自己的 FCB 中。整个系统有一张文件分配表 FAT。在 FAT 的 每个表项中存放下一个盘块号。对于 1.2 MB 的软盘,每个盘块的大小为 512 B,在每个 FAT 中共含有 2.4 K 个表项,由于每个 FAT 表项占 12 位,故 FAT 表占用 3.6 KB 的存储空间。
  现在我们来计算以盘块为分配单位时,所允许的最大磁盘容量。由于每个 FAT 表项为 12 位,因此,在 FAT 表中最多允许有 4096 个表项,如果采用以盘块作为基本分配单位, 每个盘块(也称扇区)的大小一般是 512 字节, 那么, 每个磁盘分区的容量为 2 MB (4096×512 B)。同时,一个物理磁盘支持 4 个逻辑磁盘分区,所以相应的磁盘最大容量仅 为 8 MB。这对最早时期的硬盘还可应付,但很快磁盘的容量就超过了 8 MB,FAT12 是否 还可继续用呢,回答虽是肯定的,但需要引入一个新的分配单位——簇。

  2) 簇的基本概念
  为了适应磁盘容量不断增大的需要,在进行盘块分配时,不再以盘块而是以簇(cluster) 为基本单位。簇是一组连续的扇区,在 FAT 中它是作为一个虚拟扇区,簇的大小一般是 2n (n 为整数)个盘块,在 MS-DOS 的实际运用中,簇的容量可以仅有一个扇区(512 B)、两个 扇区(1 KB)、四个扇区(2 KB)、八个扇区(4 KB)等。一个簇应包含扇区的数量与磁盘容量的 大小直接有关。例如,当一个簇仅有一个扇区时,磁盘的最大容量为 8 MB;当一个簇包含 两个扇区时,磁盘的最大容量可以达到 16 MB;当一个簇包含了八个扇区时,磁盘的最大容量便可达到 64 MB。 由上所述可以看出,以簇作为基本的分配单位所带来的最主要的好处是,能适应磁盘 容量不断增大的情况。值得注意的是,使用簇作为基本的分配单位虽可减少 FAT 表中的项 数(在相同的磁盘容量下,FAT 表的项数是与簇的大小成反比的)。这一方面会使 FAT 表占用 更少的存储空间,并减少访问 FAT 表的存取开销,提高文件系统的效率;但这也会造成更 大的簇内零头(它与存储器管理中的页内零头相似)。

  3) FAT12 存在的问题
  尽管 FAT12 曾是一个不错的文件系统,但毕竟已老化,已不能满足操作系统发展的需 要,其表现出来的主要问题是,对所允许的磁盘容量存在着严重的限制,通常只能是数十 兆字节,虽然可以用继续增加簇的大小来提高所允许的最大磁盘容量,但随着支持的硬盘 容量的增加,相应的簇内碎片也将随之成倍地增加。此外,它只能支持 8+3 格式的文件名。

  1. FAT16

  对 FAT12 所存在的问题进行简单的分析即可看出,其根本原因在于,FAT12 表最多只 允许 4096 个表项,亦即最多只能将一个磁盘分区分为 4096 个簇。这样,随着磁盘容量的 增加,必定会引起簇的大小和簇内碎片也随之增加。由此可以得出解决方法,那就是增加 FAT 表的表项数,亦即应增加 FAT 表的宽度,如果我们将 FAT 表的宽度增至 16 位,最大表 项数将增至 65536 个,此时便能将一个磁盘分区分为 65 536(216 )个簇。我们把具有 16 位表 宽的 FAT 表称为 FAT16。在 FAT16 的每个簇中可以有的盘块数为 4、8、16、32 直到 64, 由此得出 FAT16 可以管理的最大分区空间为 2 16 × 64 × 512 = 2048 MB。
  由上述分析不难看出,FAT16 对 FAT12 的局限性有所改善,但改善很有限。当磁盘容 量迅速增加时,如果再继续使用 FAT16,由此所形成的簇内碎片所造成的浪费也越大。例 如,当要求磁盘分区的大小为 8 GB 时,则每个簇的大小达到 128 KB,这意味着内部零头 最大可达到 128 KB。一般而言,对于 1~4 GB 的硬盘来说,大约会浪费 10%~20%的空间。 为了解决这一问题,微软推出了 FAT32。
  另外,由于 FAT12 和 FAT16 都不支持长文件名,文件名受到了 8 个字符文件名和 3 个 字符文件扩展名的长度限制,为了满足用户通过文件名更好地描述文件内容的需求, 在 Windows 95 以后的系统中,对 FAT16 进行了扩展,通过一个长文件名占用多个目录项的方 法,使得文件名的长度可以长达 255 个字符,这种扩展的 FAT16 也称为 VFAT。

  1. FAT32

  如同存储器管理中的分页管理,所选择的页面越大,可能造成的页内零头也会越大。 为减少页内零头就应该选择适当大小的页面。在这里,为了减小磁盘的簇内零头,也就应 当选择适当大小的簇。问题是 FAT16 表的长度只有 65 535 项,随着磁盘容量的增加,簇的 大小也必然会随之增加,为了减少簇内零头,也就应当增加 FAT 表的长度。为此,需要再 增加 FAT 表的宽度,这样也就由 FAT16 演变为 FAT32。
  FAT32 是 FAT系列文件系统的最后一个产品。每一簇在 FAT表中的表项占据4 字节(232 ), FAT 表可以表示 4 294 967 296 项,即 FAT32 允许管理比 FAT16 更多的簇。这样就允许在 FAT32 中采用较小的簇,FAT32 的每个簇都固定为 4 KB,即每簇用 8 个盘块代替 FAT16 的 64 个盘块,每个盘块仍为 512 字节,FAT32 分区格式可以管理的单个最大磁盘空间大到4 KB×2 32 = 2 TB。三种 FAT 类型的最大分区以及所对应的块的大小如图 6-11 所示。
  FAT32 比 FAT16 支持更小的簇和更大的磁盘容量,这就大大减少了磁盘空间的浪费, 使得 FAT32 分区的空间分配更有效率,例如,两个磁盘容量都为 2 GB,一个磁盘采用了 FAT16 文件系统,另一个磁盘采用了 FAT32 文件系统,采用 FAT16 磁盘的簇大小为 32 KB, 而 FAT32 磁盘簇只有 4 KB 的大小,这样,FAT32 磁盘碎片减少,比 FAT16 的存储器利用 率要高很多,通常情况下可以提高 15%。FAT32 主要应用于 Windows 98 及后续 Windows 系统,它可以增强磁盘性能,并增加可用磁盘空间,同时也支持长文件名;它不存在最小 存储空间问题,能够有效地节省硬盘空间。
  FAT32 仍然有着明显的不足之处:首先,由于文件分配表的扩大,运行速度比 FAT16 格式要慢;其次,FAT32 有最小管理空间的限制,FAT32 卷必须至少有 65 537 个簇,所以 FAT32 不支持容量小于 512 MB 的分区,因此对于小分区,则仍然需要使用 FAT16 或 FAT12; 再之,FAT32 的单个文件的长度也不能大于 4 GB;最后,FAT32 最大的限制在于兼容性方 面,FAT32 不能保持向下兼容。

  1. NTFS

  1) NTFS 新特征
  NTFS(New Technology File System)是一个专门为 Windows NT 开发的、全新的文件系 统,并适用于 Windows 2000/XP/2003。NTFS 具有许多新的特征:首先,它使用了 64 位磁 盘地址,理论上可以支持 2 的 64 次方字节的磁盘分区;其次,在 NTFS 中可以很好地支持 长文件名,单个文件名限制在 255 个字符以内,全路径名为 32 767 个字符;第三,具有系 统容错功能,即在系统出现故障或差错时,仍能保证系统正常运行,这一点我们将在 6.6 节 中介绍;第四,提供了数据的一致性,这是一个非常有用的功能,我们将在本章的最后一 节介绍;此外,NTFS 还提供了文件加密、文件压缩等功能。
  2) 磁盘组织
  同 FAT 文件系统一样,NTFS 也是以簇作为磁盘空间分配和回收的基本单位。一个文件 占用若干个簇,一个簇只属于一个文件。通过簇来间接管理磁盘,可以不需要知道盘块(扇 区)的大小,使 NTFS 具有了与磁盘物理扇区大小无关的独立性,很容易支持扇区大小不是 512 字节的非标准磁盘,从而可以根据不同的磁盘选择匹配的簇大小。
在 NTFS 文件系统中,把卷上簇的大小称为“卷因子”,卷因子是在磁盘格式化时确定 的,其大小同 FAT 一样,也是物理磁盘扇区的整数倍,即一个簇包含 2n(n 为整数)个盘块, 簇的大小可由格式化命令或格式化程序按磁盘容量和应用需求来确定,可以为 512 B、1 KB、 2 KB……,最大可达 64 KB。对于小磁盘(≤512 MB),默认簇大小为 512 字节;对于 1 GB 磁盘,默认簇大小为 1 KB;对于 2 GB 磁盘,则默认簇大小为 4 KB。事实上,为了在传输 效率和簇内碎片之间进行折中,NTFS 在大多数情况下都是使用 4 KB。
  对于簇的定位, NTFS 是采用逻辑簇号 LCN(Logical Cluster Number)和虚拟簇号 VCN(Virtual Cluster Number)进行的。LCN 是以卷为单位,将整个卷中所有的簇按顺序进行 简单的编号,NTFS 在进行地址映射时,可以通过卷因子与 LCN 的乘积,便可算出卷上的 物理字节偏移量,从而得到文件数据所在的物理磁盘地址。为了方便文件中数据的引用, NTFS 还可以使用 VCN,以文件为单位,将属于某个文件的簇按顺序进行编号。只要知道 了文件开始的簇地址,便可将 VCN 映射到 LCN。
  3) 文件的组织
  在 NTFS 中,以卷为单位,将一个卷中的所有文件信息、目录信息以及可用的未分配 空间信息,都以文件记录的方式记录在一张主控文件表 MFT(Master File Table)中。该表是 NTFS 卷结构的中心,从逻辑上讲,卷中的每个文件作为一条记录,在 MFT 表中占有一行, 其中还包括 MFT 自己的这一行。每行大小固定为 1 KB,每行称为该行所对应文件的元数 据(metadata),也称为文件控制字。
  在 MFT 表中,每个元数据将其所对应文件的所有信息,包括文件的内容等,都被组织 在所对应文件的一组属性中。由于文件大小相差悬殊,其属性所需空间大小也相差很大, 因此,在 MFT 表中,对于元数据的 1 KB 空间,可能记录不下文件的全部信息。所以当文 件较小时,其属性值所占空间也较小,可以将文件的所有属性直接记录在元数据中。而当 文件较大时,元数据仅记录该文件的一部分属性,其余属性,如文件的内容等,可以记录 到卷中的其它可用簇中,并将这些簇按其所记录文件的属性进行分类,分别链接成多个队 列,将指向这些队列的指针保存在元数据中。
  例如对于一个文件的真正数据,即文件 DATA 属性,如果很小,就直接存储在 MFT 表 中对应的元数据中,这样对文件数据的访问,仅需要对 MFT 表进行即可,减少了磁盘访问 次数,较大地提高了对小文件存取的效率。如果文件较大,则文件的真正数据往往保存在 其它簇中。此时通过元数据中指向文件 DATA 属性的队列指针,可以方便地查找到这些簇, 完成对文件数据的访问。
  实际上,文件在存储过程中,数据往往连续存放在若干个相邻的簇中,仅用一个指针 记录这几个相邻的簇即可,而不是每个簇需要一个指针,从而可以节省指针所耗费的空间。 一般地,采用上述的方式,只需十几个字节就可以含有 FAT32 所需几百个 KB 才拥有的信 息量。
  NTFS 的不足之处在于,它只能被 Windows NT 所识别。NTFS 文件系统可以存取 FAT 等文件系统的文件,但 NTFS 文件却不能被 FAT 等文件系统所存取,缺乏兼容性。Windows 的 95/98/98SE 和 Me 版本都不能识别 NTFS 文件系统。

6.3.4 索引分配

  1. 单级索引分配
    链接分配方式虽然解决了连续分配方式所存在的问题,但又出现了下述另外两个问题:

  (1) 不能支持高效的直接存取。要对一个较大的文件进行直接存取,须首先在 FAT 中顺 序地查找许多盘块号。
  (2) FAT 需占用较大的内存空间。由于一个文件所占用盘块的盘块号是随机地分布在 FAT 中的,因而只有将整个 FAT 调入内存,才能保证在 FAT 中找到一个文件的所有盘块号。 当磁盘容量较大时,FAT 可能要占用数兆字节以上的内存空间,这是令人难以接受的。 事实上,在打开某个文件时,只需把该文件占用的盘块的编号调入内存即可,完全没 有必要将整个 FAT 调入内存。为此,应将每个文件所对应的盘块号集中地放在一起。索引 分配方法就是基于这种想法所形成的一种分配方法。它为每个文件分配一个索引块(表),再 把分配给该文件的所有盘块号都记录在该索引块中,因而该索引块就是一个含有许多盘块 号的数组。在建立一个文件时,只需在为之建立的目录项中填上指向该索引块的指针。图 6-12 示出了磁盘空间的索引分配图。
  索引分配方式支持直接访问。当要读文件的第 i 个盘块时,可以方便地直接从索引块中 找到第 i 个盘块的盘块号;此外,索引分配方式也不会产生外部碎片。当文件较大时,索引 分配方式无疑要优于链接分配方式。

索引分配方式的主要问题是:

  可能要花费较多的外存空间。每当建立一个文件时,便 须为之分配一个索引块,将分配给该文件的所有盘块号记录于其中。但在一般情况下,总 是中、小型文件居多,甚至有不少文件只需 1~2 个盘块,这时如果采用链接分配方式,只 需设置 1~2 个指针。如果采用索引分配方式,则同样仍须为之分配一索引块。通常是采用 一个专门的盘块作为索引块,其中可存放成百个、甚至上千个盘块号。可见,对于小文件 采用索引分配方式时,其索引块的利用率将是极低的。

  1. 多级索引分配

  当 OS 为一个大文件分配磁盘空间时,如果所分配出去的盘块的盘块号已经装满一个索引块时,OS 便为该文件分配另一个索引块,用于将以后继续为之分配的盘块号记录于其中。 依此类推,再通过链指针将各索引块按序链接起来。显然,当文件太大,其索引块太多时, 这种方法是低效的。此时,应为这些索引块再建立一级索引,称为第一级索引,即系统再 分配一个索引块,作为第一级索引的索引块,将第一块、第二块……等索引块的盘块号填 入到此索引表中,这样便形成了两级索引分配方式。如果文件非常大时,还可用三级、四 级索引分配方式。
  图6-13示出了两级索引分配方式下各索引块之间的链接情况。如果每个盘块的大小为1 KB,每个盘块号占4个字节,则在一个索引块中可存放256个盘块号。这样,在两级索引时,最多可包含的存放文件的盘块的盘块号总数N= 256x256= 64K个盘块号。由此可得出结论:采用两级索引时,所允许的文件最大长度为64 MB。倘若盘块的大小为4 KB,在采用单级索引时所允许的最大文件长度为4 MB;而在采用两级索引时所允许的最大文件
长度可达4 GB。

  1. 混合索引分配方式

  所谓混合索引分配方式,是指将多种索引分配方式相结合而形成的一-种分配方式。 例如,系统既采用了直接地址,又采用了一级索引分配方式,或两级索引分配方式,甚至还采用了三级索引分配方式。这种混合索引分配方式已在UNIX系统中采用。在UNIX SystemV的索引结点中,共设置了13 个地址项,即iaddr(0)~ iaddr(12),如图6- 14所示。在BSD UNIX的索引结点中,共设置了13个地址项,它们都把所有的地址项分成两类,即直接地址和间接地址。
  1) 直接地址
  为了提高对文件的检索速度,在索引结点中可设置 10 个直接地址项,即用 iaddr(0)~ iaddr(9)来存放直接地址。换言之,在这里的每项中所存放的是该文件数据所在盘块的盘块 号。假如每个盘块的大小为 4 KB,当文件不大于 40 KB 时,便可直接从索引结点中读出该 文件的全部盘块号。
  2) 一次间接地址
  对于大、中型文件,只采用直接地址是不现实的。为此,可再利用索引结点中的地址 项 iaddr(10)来提供一次间接地址。这种方式的实质就是一级索引分配方式。图中的一次间 址块也就是索引块,系统将分配给文件的多个盘块号记入其中。在一次间址块中可存放 1 K 个盘块号,因而允许文件长达 4 MB。
  3) 多次间接地址
  当文件长度大于 4 MB + 40 KB 时(一次间址与 10 个直接地址项),系统还须采用二次间 址分配方式。这时,用地址项 iaddr(11)提供二次间接地址。该方式的实质是两级索引分配 方式。系统此时是在二次间址块中记入所有一次间址块的盘号。在采用二次间址方式时, 文件最大长度可达 4 GB。同理,地址项 iaddr(12)作为三次间接地址,其所允许的文件最大 长度可达 4 TB。

6.4 目录管理

  通常,在现代计算机系统中,都要存储大量的文件。为了能对这些文件实施有效的管 理,必须对它们加以妥善组织,这主要是通过文件目录实现的。文件目录也是一种数据结 构,用于标识系统中的文件及其物理地址,供检索时使用。对目录管理的要求如下:

  (1) 实现“按名存取”,即用户只须向系统提供所需访问文件的名字,便能快速准确地 找到指定文件在外存上的存储位置。这是目录管理中最基本的功能,也是文件系统向用户 提供的最基本的服务。
  (2) 提高对目录的检索速度。通过合

以上是关于文件管理======的主要内容,如果未能解决你的问题,请参考以下文章

华为手机文件管理器

Android 调用系统文件管理器

DELPHI基础教程:文件管理(一)[2]

iOS苹果手机最好用的文件管理器

文件管理与重定向

如何高效实现公司文件管理?