文件是由操作系统来管理的,包括文件的结构、文件的命名、文件的使用、文件的保护和文件的实现等,这些都是在操作系统的设计当中需要解决的问题。总之,在一个操作系统中,负责处理文件相关事宜的部分,就称为文件系统。
可以从两个观点来看待文件系统:
用户观点:所谓用户,就是计算机的使用者以及应用程序的编程人员。对于他们来说,他们关心的是文件系统所提供的对外的用户接口,包括文件如何命名、如何保护、如何访问(创建、打开、关闭、读和写等)
操作系统观点:对于操作系统的设计者来说,他们关心的是如何来实现与文件有关的各个功能模块,包括如何来管理存储空间、文件系统的布局、文件的存储位置如何安排等。
1、文件
1.1文件的基本概念
- 文件的命名
文件名.后缀
- 文件的结构
主要有三种形式:
①无结构:整个文件由一序列无结构的字节流组成。
②简单的记录结构:用每一行作为一个记录,每个记录的长度可以是固定不变的,也可以是各不相同的。
③复杂结构:文件的结构形式比较复杂。比如,可以把文件中的所有记录组织成一颗树的形式,即树形结构。
记录结构和复杂结构都是由操作系统来指定文件的逻辑结构,使用起来很不方便。
UNIX和Windows,它们采用的都是无结构形式,用户可以将信息以任意格式写入文件中。
- 文件的分类
在UNIX中,还有两种特殊文件,其实就是输入输出设备,在UNIX中将输入输出设备看成是一种文件。包括字符特殊文件和块特殊文件。
- 文件的属性
1.2、文件的使用
2、目录
2.1、目录的基本概念
2.2、目录的结构
- 一级目录
- 二级目录
- 多级目录
现代操作系统一般采用的都是多级目录结构,也称为是树状目录结构或层次目录结构,其形状好似一颗倒立的树。
绝对路径名:对于一个文件或目录,可以用从根目录开始依次经由的各级目录名,再加上最终的文件名或目录名来表示。\spll\mail\copy\all
相对路径名:在当前目录下,如果需要访问一个文件或目录时,可以使用相对于这个当前目录的部分路径名,即相对路径名。
例如:假如当前工作目录是:\spll\mail\copy,那么以下两个路径名是完全等价的:
\spll\mail\copy\all 绝对路径名
all 相对路径名
3、文件系统的实现
3.1、文件系统的布局
将磁盘分区以后,磁盘的扇区0称为主引导记录(Master Boot Record,MBR),它主要用来启动计算机。在MBR的末尾有一个分区表,里面记录了每一个分区的起始扇区和大小。在磁盘的多个分区中,有一个是活动分区,操作系统就保存在该分区中。
- 当一台计算机启动后,位于主板上的BIOS(Basic Input Output System,基本输入输出系统)程序就会被执行。
- 该程序会去检查并设置系统当中的各种硬件资源,然后去查询一个表格,看看是从什么地方启动的,是软盘、硬盘还是光盘。
- 如果是从硬盘启动的,那么它就会把MBR中的引导程序装入到内存运行,
- 然后该引导程序就会去查询硬盘上的分区表,看看哪一个是活动分区。
- 如果第二个是活动分区,就会把该分区的引导块当中的程序装入到内存中去运行。当这个程序开始运行时,它就会把保存在这个磁盘分区中的操作系统程序,一步步地装入到内存中去运行。
3.2、文件的实现
- 文件控制块
文件控制块(File Control Block,FCB)是操作系统为管理文件而设置的一种数据结构,里面存放了与一个文件有关的所有管理信息,它是文件存在的标志。
文件控制块的主要内容:
①文件的类型和长度
②文件的所有者、文件的访问权限
③文件的创建时间、最后访问时间、最后修改时间
④文件所在的物理块信息,即该文件在磁盘上的存放位置,它的每一个逻辑块被存放在磁盘的哪一个物理块中。
总之,只有知道了这些信息,文件系统才能对这个文件的数据进行访问。
备注:
FCB和进程控制块PCB有些类似,在一个进程的PCB中,保存的是与该进程有关的所有管理信息。但是区别是:PCB是存放在内存中,而且是在进程运行时创建,在进程结束时撤销;而FCB是存放在磁盘上的。
- 文件的物理结构
文件的物理结构讨论的是如何把一个文件存放在磁盘等物理介质上。具体说,就是以块为单位,研究如何把文件的一个个连续的逻辑块分别存放在不同的物理块中,即研究逻辑块与物理块的映射关系。(有点类似于,逻辑页面和物理页面之间的映射关系。)
一般,文件的物理结构只要有三种形式:连续结构,链表结构和索引结构。
- 连续结构
连续结构也称为顺序结构,它的基本思想是把文件的各个逻辑块按照顺序存放在若干个连续的物理块中。也就是说,文件的逻辑地址是连续的;把它存放在磁盘上以后,物理地址也是连续的。
优点:
①简单、易于实现。对于文件系统来说,记住第一个物理块的编号和物理块的个数,即可通过简单的加法来实现逻辑块到物理块的映射关系。
②由于物理块是顺序存放的,所以在访问文件时,只要将磁头定位到第一个物理块,即可顺序地读取每一个数据块,而不用再去移动磁头,或等待相应的扇区旋转到磁头的下方。这样,磁盘的访问速度是非常快的。
缺点:
①随着磁盘上的文件的增加和删除,将会形成已占有物理块与空闲物理块之间相互交错的情形。这样那些小的,无法再利用的物理块,就成了外碎片。
②文件的大小不能动态地增长,在创建一个新的文件时,必须事先指定该文件的大小,这样文件系统才知道应该把哪一片连续的空闲空间分配给它。但是在新建一个文件的时候,我们往往不知道文件的大小,或者说文件的大小是变化的。
总之,连续结构的文件系统已经不常用了。但是在CD-ROM、DVD和其它一些一次性写入的光学存储介质中,连续结构被广泛应用。
- 链表结构
链表结构的基本思路是:把文件的各个逻辑块依次存放在若干个物理块中,这些物理块既可以是连续的,也可以是不连续的,然后在各个物理块之间通过指针连接起来,前一个物理块指向下一个物理块。
每一个物理块由两个部分组成:指针和数据区。
对于文件系统来说,它只要记住这个链表结构的首结点指针,就可以定位到该文件中的任何一个物理块,这相当于是链表的遍历。
缺点:
①在访问一个文件时,只能进行顺序访问,不能随机访问,否则速度会很慢。只能从头开始访问。
②每个物理块上的数据存储空间不再是2的整数次幂,因为指针要占用若干个字节,这样,就使得文件的访问不太方便。
- 带有文件分配表的链表结构
基本思路:在链表结构的基础上,把每一个物理块当中的链表指针抽取出来,单独组成一个表格,即文件分配表(File Allocation Table,FAT),然后把它存放在内存中。
备注:FAT是存放在磁盘上的,然后在需要的时候再调入到内存中。
如何知道一个逻辑块所对应的物理块地址呢?
- 在链表结构中,这个地址信息保存在一条链表中,而这个链表中每个指针又保存在磁盘上,是和文件的数据混合在一起的,既占用磁盘空间,访问速度又慢。
- 如果有文件分配表的话:一方面,可以把指针信息拿出来放在内存中;另一方面,查询这个FAT表,找到相应的物理块地址,然后根据这个地址再去访问磁盘。只要访问一次就可以了。
如何来实现文件分配表?
在整个文件系统中,只设置一个一维的线性表格。它的表格项的个数等于磁盘上物理块的个数(缺点:太大,包括那些没有打开的文件),并且按照物理块编号的顺序来建立索引。对于一个文件,在它的文件控制块(FCB)中记录了该文件的第一个物理块的编号x1,然后再FAT表的第x1项中,记录了该文件的第二个物理块编号x2,依次类推,形成一条链表。然后在最后一条FAT表项中,存放一个特殊的文件结束的标识。
- 索引结构
索引结构的基本思路:把一个文件中的每一个逻辑块所对应的物理块编号直接记录在文件的FCB中,称为i结点(索引结点)。这样,对于系统中的每一个文件,都有一个自己的索引结点。
在索引结构方式下,只要把那些正在使用的文件的索引结点装入到内存即可,而对于那些没有被打开的文件,则不必装入到内存。
在这种方式下,目录项的内容已经发生了变化。里面存放的不是文件的首个物理块的编号,而是该文件的i结点所在的物理块编号。
文件名 | 索引块 |
main.c | 20 |
3.3、目录的实现
- 目录项的内容
文件名 | FCB |
f1.exe | FCB1 |
f2.c | FCB2 |
f3.txt | FCB3 |
文件名 | FCB索引 |
f1.exe | FCB1的地址 |
f2.c | FCB2的地址 |
f3.txt | FCB3的地址 |
- 长文件名问题
如何实现这种长文件名的机制?
- 有三种方法在目录项中,将文件名的长度固定为255个字符,即为每一个文件名都预留255个字节的空间。缺点就是,会造成浪费大量的目录空间。
- 每一个目录项的长度是可变的,对于不同长度的文件名,其目录项的长度是不一样的。每一个目录项的内容分为三个部分:目录项的长度,文件的属性信息和文件名。
- 每一个目录项本身的长度是固定的,然后把长度可变的文件名统一放在目录文件的末尾。这样,当一个目录项被释放以后,它所占用的空间就能方便地回收和利用。
- 目录的搜索方法
目录的搜索:就是在一个目录文件中,当给定了一个文件名以后,如何定位到相应的目录项。寻找目录项的目的在于取出该文件的FCB,这样就能访问它的各种属性信息。
难点:用户给出的是ASCII形式的文件名,系统如何通过这个文件名来作为索引?
目录的搜索方法主要有两种:
- 线性搜索:对目录中的每一个目录项,依次与该文件名进行比较,直到找到相应的目录项。
- Hash表:用Hash表的方法来加速搜索速度。
3.4、系统调用的实现
- 数据结构
①位于外存上的数据结构:
目录结构:用来组织文件,可以通过文件名来寻找相应的FCB。
文件控制块:记录了文件的各种属性信息和文件在外存的存储信息。
②位于内存中的数据结构:
系统内打开文件表:它记录了在整个系统中,所有被打开的文件,它们的文件控制块和共享计数值等信息。
进程内打开文件表:每一个进程都有这样一张表格,它描述了在进程内部所有打开的文件,包括每一个文件的打开方式,当前读写指针,该文件在系统打开文件表中的索引等信息。
- 打开文件
- 关闭文件
文件在使用完毕后必须关闭,系统调用函数为:close(fd);
- 读文件
读文件的系统调用函数为:int read(fd, userBuf, size);
fd是文件指针,userBuf是用户提供的一个缓冲区,size是需要读取的字节数。功能是:从文件fd的当前位置开始,顺序读取大小为size的数据块,并保存在缓冲区userBuf中。
3.5、空闲空间管理
- 位图法
用位图来表示磁盘的空闲空间列表。每一个物理块用一个位来表示。如果该物理块空闲,则相应位为1,;如果该物理块被分配,则相应位为0;
- 链表法
用链表来表示磁盘的空闲空间列表。在每一个空闲的物理块上都有一个指针,然后把所有的空闲块通过这个指针连接起来,从而形成一条链表。系统只要记住这条链表的首结点指针,就可以一个接一个去访问所有的空闲物理块。
- 索引法
它不是把所有的空闲物理块链接成一条链表,而是单独预留少量的一些空闲物理块,把它们链接成一条链表。