实验五 文件系统
1 实验简介
本实验要求在模拟的I/O系统之上开发一个简单的文件系统。用户通过create, open, read等命令与文件系统交互。文件系统把磁盘视为顺序编号的逻辑块序列,逻辑块的编号为0至L − 1。I/O系统利用内存中的数组模拟磁盘。
2 I/O系统
实际物理磁盘的结构是多维的:有柱面、磁头、扇区等概念。I/O系统的任务是隐藏磁盘的结构细节,把磁盘以逻辑块的面目呈现给文件系统。逻辑块顺序编号,编号取值范围为0至L−1,其中L表示磁盘的存储块总数。实验中,我们可以利用数组ldisk[C][H][B]构建磁盘模型,其中CHB 分别表示柱面号,磁头号和扇区号。每个扇区大小为512字节。I/O系统从文件系统接收命令,根据命令指定的逻辑块号把磁盘块的内容读入命令指定的内存区域,或者把命令指定的内存区域内容写入磁盘块。文件系统和I/O系统之间的接口由如下两个函数定义:
• read_block(int i, char *p);
该函数把逻辑块i的内容读入到指针p指向的内存位置,拷贝的字符个数为存储块的长度B。
• write block(int i, char *p);
该函数把指针p指向的内容写入逻辑块i,拷贝的字符个数为存储块的长度B。此外,为了方便测试,我们还需要实现另外两个函数:一个用来把数组ldisk 存储到文件;另一个用来把文件内容恢复到数组。
3 文件系统
文件系统位于I/O系统之上。
3.1 用户与文件系统之间的接口
文件系统需提供如下函数;create, destroy, open, read, write。
• create(filename): 根据指定的文件名创建新文件。
• destroy(filename): 删除指定文件。
• open(filename): 打开文件。该函数返回的索引号可用于后续的read, write, lseek,或close操作。
• close(index): 关闭制定文件。
• read(index, mem_area, count): 从指定文件顺序读入count个字节memarea指定的内存位置。读操作从文件的读写指针指示的位置开始。
• write(index, mem_area, count): 把memarea指定的内存位置开始的count个字节顺序写入指定文件。写操作从文件的读写指针指示的位置开始。
• lseek(index, pos): 把文件的读写指针移动到pos指定的位置。pos是一个整数,表示从文件开始位置的偏移量。文件打开时,读写指针自动设置为0。每次读写操作之后,它指向最后被访问的字节的下一个位置。lseek能够在不进行读写操作的情况下改变读写指针能位置。
• directory: 列表显示所有文件及其长度。
3.2 文件系统的组织
磁盘的前k个块是保留区,其中包含如下信息:位图和文件描述符。位图用来描述磁盘块的分配情况。位图中的每一位对应一个逻辑块。创建或者删除文件,以及文件的长度发生变化时,文件系统都需要进行位图操作。前k个块的剩余部分包含一组文件描述符。每个文件描述符包含如下信息:
• 文件长度,单位字节
• 文件分配到的磁盘块号数组。该数组的长度是一个系统参数。在实验中我们可以把它设置为一个比较小的数,例如3。
3.3 目录
我们的文件系统中仅设置一个目录,该目录包含文件系统中的所有文件。除了不需要显示地创建和删除之外,目录在很多方面和普通文件相像。目录对应0号文件描述符。初始状态下,目录中没有文件,所有,目录对应的描述符中记录的长度应为0,而且也没有分配磁盘块。每创建一个文件,目录文件的长度便增加一分。目录文件的内容由一系列的目录项组成,其中每个目录项由如下内容组成:
• 文件名
• 文件描述符序号
3.4 文件的创建与删除
创建文件时需要进行如下操作;
• 找一个空闲文件描述符(扫描ldisk [0]~ldisk [k - 1])
• 在文件目录里为新创建的文件分配一个目录项(可能需要为目录文件分配新的磁盘块)
• 在分配到的目录项里记录文件名及描述符编号.
• 返回状态信息(如有无错误发生等)
删除文件时需要进行如下操作(假设文件没有被打开):
• 在目录里搜索该文件的描述符编号
• 删除该文件对应的目录项并更新位图
• 释放文件描述符
• 返回状态信息
3.5 文件的打开与关闭
文件系统维护一张打开文件表.打开文件表的长度固定,其表目包含如下信息:
• 读写缓冲区
• 读写指针
• 文件描述符号
文件被打开时,便在打开文件表中为其分配一个表目;文件被关闭时,其对应的表目被释放。读写缓冲区的大小等于一个磁盘存储块。打开文件时需要进行的操作如下:
• 搜索目录找到文件对应的描述符编号
• 在打开文件表中分配一个表目
• 在分配到的表目中把读写指针置为0,并记录描述符编号
• 读入文件的第一块到读写缓冲区中
• 返回分配到的表目在打开文件表中的索引号
关闭文件时需要进行的操作如下:
• 把缓冲区的内容写入磁盘
• 释放该文件在打开文件表中对应的表目
• 返回状态信息
3.6 读写
文件打开之后才能进行读写操作.读操作需要完成的任务如下:
1. 计算读写指针对应的位置在读写缓冲区中的偏移
2. 把缓冲区中的内容拷贝到指定的内存位置,直到发生下列事件之一:
• 到达文件尾或者已经拷贝了指定的字节数。这时,更新读写指针并返回相应信息
• 到达缓冲区末尾。这时,把缓冲区内容写入磁盘,然后把文件下一块的内容读入磁盘。最后返回第2步。
4 实验内容
为了能够对我们的模拟系统进行测试,请编写一个操纵文件系统的外壳程序或者一个菜单驱动系统。
5实验步骤
1. 打开文件系统
(1) 操作源程序
2. 关闭文件系统
(1) 操作源程序
3. 获取文件指针
(1) 操作源程序
4. 建立文件
(1) 算法思想
新建一个文件,设置文件夹的大小与创建日期,并遵守命名规
则进行命名,系统判断磁盘大小以及命名方式是否符合规定,
如果符合则创建文件成功,否则失败。
(2) 操作源程序
(3) 测试源程序
(4) 流程图
5. 文件重命名
(1) 算法思想
对文件进行重命名,判断新命名是否与文件系统中其他文件重
名以及文件名长度是否符合要求,如果满足要求,则重命名成
功,否则命名失败。
(2) 操作源程序
(3) 测试源程序
(4) 流程图
6. 显示文件目录
(1) 算法思想
将系统中所有文件信息罗列出来
(2) 操作源程序
(3) 测试源程序
7. 删除文件
(1) 算法思想
找到要删除的文件,文件存在且处于关闭状态则进行删除操作。
(2) 操作源程序
(3) 测试源程序
(4) 流程图
8. 打开文件
(1) 算法设计
判断要打开的文件是否存在,存在则打开文件,不存在则提示
错误。
(2) 操作流程图
(3) 测试源程序
(4) 流程图
9. 关闭文件
(1) 算法思想
判断要关闭的文件是否存在并,如果存在,判断文件是否打开,如果是关闭文件,否则操作失败。
(2) 操作源代码
(3) 测试源程序
(4) 流程图
10. 读文件
(1) 算法思想
判断要读取的文件是否存在,如果存在,则判断文件是否存在,如果存在则判断文件是否处于打开状态,如果处于打开状态,则进行文件读取操作,否则提示文件未打开。
(2) 操作源程序
(3) 测试源程序
(4) 流程图
11. 写文件
(1) 算法思想
判断要进行写的文件是否存在,如果存在,则判断文件是否存
在,如果存在则判断文件是否处于打开状态,如果处于打开状
态,则进行文件写操作,否则提示文件未打开。
(2) 源程序
(3) 测试源程序
(4) 流程图
12. 判断文件结束
(1) 源程序
13. 获取文件指针
(1) 源程序
14. 设置文件指针
(1) 源程序
15. 主函数
(1) 源程序
(2) 主函数调用结构图
(3) 流程图
6实验测试
1. 创建文件系统
2. 创建文件
① 创建新文件
② 创建新文件如果该文件名和已有文件名相同则提示
3. 显示文件目录
4. 文件重命名
① 重新命名文件中不存在相同名字的文件。
② 文件重新命名,系统中有相同名字的文件
5. 打开文件
① 打开存在文件
② 打开不存在文件则会提示
③ 打开已经打开文件
6. 删除文件
① 删除存在并处于关闭状态的文件
② 删除已经被打开的文件提示错误
7. 写文件
8. 读文件
9. 关闭文件
10. 退出文件系统