文件的基本概念
文件就是一组按照某种格式组织的具有完整逻辑意义的信息。
从使用和创建文件的用户角度来看,文件是磁盘的最小存储单元,用户数据除非在文件中,否则不能保存到磁盘;从进程的角度来看,文件是一种进程可以对它进行访问的,但独立于进程而存在的数据结构,文件中的信息不会因进程的死亡而消失,除非文件的属主显式地删除它;从操作系统的角度来看,文件是一个逻辑上连续的数据集合,它仅向系统提供文件管理所必须的属性。
文件属性
磁盘中的文件数据的含义只能由用户程序来解释,而文件系统只对它们的存储和管理负责。但是,文件必须向文件系统提供用于管理的必要信息和属性。同样,文件系统也会为文件添加一些用于管理的属性,这些属性通常为:
- 名称:为方便用户对文件的引用,文件要有一个用字符串表示的文件名;
- 位置:文件在磁盘中的存储位置;
- 大小:以字节计算的文件大小;
- 类型:为对不同格式的文件进行区分,不同文件有不同的类型。文件以文件扩展名的形式来表示文件的类型;
- 保护:由用户或者系统管理人员设置的,用来表示文件访问权限的属性;
- 时间、日期:为了查询方便,文件上通常都要标有文件建立时间、文件最近修改时间等于时间有关的属性;
- 用户标识:该属性用来记录文件的拥有者。
常见的文件扩展名如下表所示:
文件类型 | 扩展名 | 说明 |
可执行文件 | exe、com、bin | 可执行的机器语言程序 |
目标文件 | obj、o | 已经编译完成但尚未连接的机器语言代码 |
源文件 | c、cpp、java、pas、asm、a | 各种语言的源代码 |
批处理文件 | bat、sh | 命令解释器接受并解释的命令文件 |
文本文件 | txt、doc | 文本数据文件 |
文字处理文件 | wp、tex、rtf、doc | 由文字处理器产生的文件 |
库文件 | lib、so、dll | 应用程序可共享的程序库文件 |
打印或图文件 | ps、pdf、jpg | 用于打印或显示使用的文件 |
多媒体文件 | mpeg、mov、rm | 音频或视频文件 |
压缩文件 | zip、rm | 多个文件组织在一个文件中并被压缩的文件 |
普通文件分类
对于普通文件,从不同角度有不同的分类方法。
从文件保存的数据形式来看,文件有程序源文件、目标文件、可执行文件等。源文件是由用户从终端输入的文件,它通常由ASCII码或者其他文字所组成;目标文件是源文件经汇编或编译之后得到的文件,它是一种二进制文件;可执行文件是经过编译连接形成的计算机可执行的文件。
从文件的读写权限来看,分为只读文件、读写文件和可执行文件。仅允许用户进行读操作的文件叫做只读文件;用户既可以读也可以写的文件叫做读写文件;可执行文件则是只允许用户使用,通常不能对其进行读写操作。
从文件在磁盘上的保存方式来看,有临时文件和永久文件。临时文件通常都是用于数据缓冲的中间文件,它是在用户程序的执行中根据当时的需要建立的,这种文件会随着程序运行的结束而被系统自动删除。
如果从文件的管理者——操作系统的角度来看,上面的所有的这些文件只有两种文件:可执行文件(即程序文件)和数据文件。因为作为文件管理者,操作系统对于那些数据文件的任务还是为了用户保存或打开它们,至于其内容则由用户解释,与操作系统无关;而对于可执行文件则不同,操作系统必须解释并运行它们。
进程、操作系统与文件之间的关系
进程要通过操作系统来访问磁盘上的文件,也就是说,操作系统是进程与磁盘文件系统之间的中介。它们之间关系如下图所示:
而文件经过文件系统和操作系统的封装之后,最终文件系统呈现给用户的界面如下所示:
也就是说,用户看到的是经过一级级目录组织的文件,以及为用户提供的一组对文件进行操作的系统调用,例如创建文件的greate()、删除文件的delete()、打开文件的open()、关闭文件的close()、读文件的read()、写文件的write(),等等。
用户对文件的主要操作
在任何计算机系统中,文件操作命令都是普通用户管理文件的主要手段,是操作系统提供给用户的主要接口。主要操作如下:
- 创建文件:两个步骤,首先在文件系统中为被创建文件寻找一个存储空间,然后在目录文件中为其创建一个条目,并在该条目上记录该文件的名称、大小、时间、拓展名、权限、位置等信息;
- 写文件:首先按照用户输入的文件目录和文件名查找该文件,后验证用户权限。若该用户拥有对该文件的写权限,则将文件打开并把文件的句柄交给当前进程控制块,由进程对其进行写操作。在写文件过程中,系统还必须为该文件维护一个写位置指针,以跟踪写的位置;
- 读文件:首先按照用户输入的文件目录和文件名查找该文件,后验证用户权限。若该用户拥有对该文件的读权限,则将文件打开并把文件的句柄交给当前进程控制块,由进程对其进行读操作。当然,系统还必须为该文件维护一个读位置指针;
- 删除文件:系统按照用户输入的文件目录和文件名查找该文件,权限验证通过后,然后释放该文件所占的存储空间并删除该文件在目录文件中的相应条目。
由上面的介绍可知,从文件用户的角度来看,操作系统的文件管理系统必须提供两项基本功能:一是要建立专门用于文件管理的目录体系;而是要为用户提供对文件进行操作的系统调用。
文件的简单存储方式
经过适当的软硬件处理,磁盘可以看成是如下图所示,由若干大小相等的“存储块”所组成的一个线性空间。为了对块进行识别,磁盘上的每一个块都有一个编号。
通常一个文件需要占用多个存储块。为了方便查找和访问,需要一个结构类型的数据来记录文件的名称、存储位置、文件所有者、文件创建时间等信息。也就是说,磁盘文件系统中需要一个目录表来记录文件名称、存储位置等信息,并把这种记录叫做目录项,这个目录表就叫做目录文件,并被存放在磁盘上。目录文件是文件系统的自用文件,为了与用户文件相区别,人们就把用户文件叫做普通文件,系统自用文件叫做特殊文件。
一种最简单的文件存储方式如下所示:
存储块的组织方式
其实,在实际应用中,由于各种原因,一个文件常常不是如上图占用一片连续的存储块,而是如下图所示占用不连续的存储块。也就是说,一个连续文件实际占用的存储块可能连续,也可能不连续,但必须保证从用户的角度看,它是连续且完整的。于是,在文件系统的发展中,为实现上述要求,在文件存储块的组织方式上就形成了多种方式。
存储块的链接组织方式
所谓链接组织方式,就是把同一个文件的这些不连续的存储块,按照文件的逻辑顺序链接成为一个链表。即在属于同一个文件的所有存储块中都保有一个指向它的后续存储块的指针,由这些指针来维护文件的逻辑顺序。
上图就是一个采用链接组织方式,依次占用了7、2、8、20、5号存储块的文件。文件的首块指针和尾块指针都被存放在文件目录中。而文件的每一个存储块都包含下一个存储块的指针,这样当操作系统的文件管理系统在通过文件名获得了文件首块指针之后,就可以根据块中指针的指示,依次访问该文件的所有存储块,并将文件信息呈现给文件用户,从而使用户看到的是一个连续文件。
目前常用的文件分配表(File Allocation Table,FAT)方式就是链接组织方式的一种变形。在这种方式中,存储块的链接关系被单独制作成了一张表——文件分配表。所谓文件分配表,就是一个以存储块号为下标的一个数组,由于该数组的元素与存储块一一对应,所以就可以用数组元素来描述文件占用存储块的情况。为了表示文件所占用存储块的逻辑顺序,在每个数组元素中填写的都是文件下一个存储块所对应的数组元素的下标。
文件分配表方式如下图所示:
例如:如果某一个外存储器共有i个存储块,那么就制作一个具有i行的数组,每一个数组元素都代表一个存储块,下标i就代表第i块;如果这个第i块是属于某一个文件的,那么在第i行的表格中存放的就是这个文件下一个存储块对应的数组元素的下标。这个下标其实是一个指针,它有两个作用:一方面它指向文件占用数组的下一个元素;另一方面指向了文件存储块。
存储块的索引组织方式
另一个很自然的方式是,为每一个文件创建一个长度与文件所占用存储块的数目相等的数组,以文件块的逻辑顺序号为数组元素的下标,而以文件存储块的指针为元素的内容,于是就形成了一个文件的索引表。简单地说,索引表就是文件块的逻辑块号与存储块号的对照表。
下图表示一个按照逻辑顺序占用5、3、20、1号存储块的文件索引表与文件之间的关系:
可以看到,这种表很像内存管理中的页表。同样,当文件比较大时,也可以使用多级索引结构。
空闲块的记录
未被文件所占用,或者被已删除文件释放出来的块叫做外存的空闲块。作为文件的管理者,操作系统必须随时掌握和了解空闲块的情况,以便在需要保存一个新文件时为其分配存储块。操作系统用来记录跟踪空闲块的数据结构主要有位图、链表、分组链表等。
所谓位图管理方式,就是以数据的一个二进制位来表示对应存储块的空闲状态:如果存储块未被占用,则在该位记录为0;否则记录为1。
由于使用位操作指令可以方便地实现位图操作,并且现代处理器一般都具有这种位操作指令,所以很多文件系统都采用这种位图来对磁盘空闲块进行管理。
所谓链表管理方式,就是把空闲块的集合看成是一个空文件。即把所有空闲存储块用链表链接起来,链表的头指针指向第一个空闲存储块,而在这个存储块中包含有下一个存储块指针,以此类推,就可以把所有空闲存储块链接在一起了。
分组链表方式就是链表方式的改进方案,就是在n个存储块中拿出一个存储块,专门用来存储其余n-1个存储块的指针,而把存储指针的存储块作为链表的节点,再链接成一个链表。
使用链表管理方式的最大优点就是,能快速地找到大量空闲的存储块。