操作系统课程设计指导书2015(8)

2019-04-16 22:41

(3)输入参数说明:

stream:使用fopen()打开的文件的指针,用于指示要定位读写指针的文件; offset:位移量,以字节为单位; origin:初始位置,有三个常量:

SEEK_CUR:读写指针当前位置; SEEK_SET:文件开头; SEEK_END:文件末尾。

当origin值为SEEK_CUR 或SEEK_END时,参数offset可以为负值。

3.3实例系统的设计与实现

本实例系统是仿照FAT16文件系统来设计实现的,但根目录没有采用FAT16的固定位置、固定大小的根目录区,而是以根目录文件的形式来实现的,这也是目前主流文件系统对根目录的处理方式。

3.3.1 数据结构设计

1.需要包含的头文件 (1)#include

(2)#include (3)#include (4)#include

2.定义的常量

(1)#define BLOCKSIZE 1024 磁盘块大小

(2)#define SIZE 1024000 虚拟磁盘空间大小 (3)#define END 65535 FAT中的文件结束标志 (4)#define FREE 0 FAT中盘块空闲标志 (5)#define ROOTBLOCKNUM 2 根目录区所占盘块总数 (6)#define MAXOPENFILE 10 最多同时打开文件个数 3.数据结构

(1)文件控制块FCB

用于记录文件的描述和控制信息,每个文件设置一个FCB,它也是文件的目录项的内容。

typedef struct FCB //仿照FAT16设置的

{ char filename[8]; //文件名 char exname[3];//文件扩展名 unsigned char attribute;//文件属性字段:为简单起见,我们只为文件设置了两种属性:

//值为0时表示目录文件,值为1时表示数据文件

unsigned short time;//文件创建时间 unsigned short data;//文件创建日期

- 36 -

unsigned short first;//文件起始盘块号 unsigned long length;//文件长度(字节数)

char free;//表示目录项是否为空,若值为0,表示空,值为1,表示已分配

}fcb;

(2)文件分配表FAT 在本实例中,文件分配表有两个作用:一是记录磁盘上每个文件所占据的磁盘块的块号;二是记录磁盘上哪些块已经分配出去了,哪些块是空闲的,即起到了位示图的作用。若FAT中某个表项的值为FREE,则表示该表项所对应的磁盘块是空闲的;若某个表项的值为END,则表示所对应的磁盘块是某文件的最后一个磁盘块;若某个表项的值是其他值,则该值表示某文件的下一个磁盘块的块号。为了提高系统的可靠性,本实例中设置了两张FAT表,它们互为备份,每个FAT占据两个磁盘块。

typedef struct FAT { unsigned short id;

}fat; (3)用户打开文件表USEROPEN 当打开一个文件时,必须将文件的目录项中的所有内容全部复制到内存中,同时还要记录有关文件操作的动态信息,如读写指针的值等。在本实例中实现的是一个用于单用户单任务系统的文件系统,为简单起见,我们把用户文件描述符表和内存FCB表合在一起,称为用户打开文件表,表项数目为10,即一个用户最多可同时打开10个文件。然后用一个数组来描述,则数组下标即某个打开文件的描述符。另外,我们在用户打开文件表中还设置了一个字段“char dir[80]”,用来记录每个打开文件所在的目录名,以方便用户打开不同目录下具有相同文件名的不同文件。

typedef struct USEROPEN { char filename[8]; //文件名 char exname[3];//文件扩展名 unsigned char attribute;//文件属性:值为0时表示目录文件,值为1时表示数据文件 unsigned short time;//文件创建时间 unsigned short data;//文件创建日期 unsigned short first;//文件起始盘块号 unsigned long length;//文件长度(对数据文件是字节数,对目录文件可以是目录项个数)

char free;//表示目录项是否为空,若值为0,表示空,值为1,表示已分配

//前面内容是文件的FCB中的内容。

// 下面设置的dirno和diroff记录了相应打开文件的目录项在父目录文件中的位置,

//这样如果该文件的fcb被修改了,则要写回父目录文件时比较方便

int dirno; //相应打开文件的目录项在父目录文件中的盘块号

int diroff;// 相应打开文件的目录项在父目录文件的dirno盘块中的目录项序号 char dir[MAXOPENFILE][80]; //相应打开文件所在的目录名,这样方便快速检查出

//指定文件是否已经打开

int count; //读写指针在文件中的位置

- 37 -

char fcbstate; //是否修改了文件的FCB的内容,如果修改了置为1,否则为0

char topenfile; //表示该用户打开表项是否为空,若值为0,表示为空,否则表示已

//被某打开文件占据

}useropen; (4)引导块BLOCK0 在引导块中主要存放逻辑磁盘的相关描述信息,比如磁盘块大小、磁盘块数量、文件分配表、根目录区、数据区在磁盘上的起始位置等。如果是引导盘,还要存放操作系统的引导信息。本实例是在内存的虚拟磁盘中创建一个文件系统,因此所包含的内容比较少,只有磁盘块大小、磁盘块数量、数据区开始位置、根目录文件开始位置等。

typedef struct BLOCK0 //引导块内容 {

//存储一些描述信息,如磁盘块大小、磁盘块数量、最多打开文件数等、

char information[200];

unsigned short root; //根目录文件的起始盘块号 unsigned char *startblock; //虚拟磁盘上数据区开始位置

}block0;

4.全局变量定义

(1)unsigned char *myvhard: 指向虚拟磁盘的起始地址

(2)useropen openfilelist[MAXOPENFILE]: 用户打开文件表数组 (3)useropen *ptrcurdir: 指向用户打开文件表中的当前目录所在打开文件表项的位置; (4)char currentdir[80]: 记录当前目录的目录名(包括目录的路径) (5)unsigned char* startp: 记录虚拟磁盘上数据区开始位置 5.虚拟磁盘空间布局

由于真正的磁盘操作需要涉及到设备的驱动程序,所以本实例是在内存中申请一块空间作为虚拟磁盘使用,我们的文件系统就建立在这个虚拟磁盘上。虚拟磁盘一共划分成1000个磁盘块,每个块1024个字节,其布局格式是模仿FAT文件系统设计的,其中引导块占一个盘块,两张FAT各占2个盘块,剩下的空间全部是数据区,在对虚拟磁盘进行格式化的时候,将把数据区第1块(即虚拟磁盘的第6块)分配给根目录文件,如图3-3所示:

块数1块引导块2块FAT12块FAT2995块数据区 图3-3 虚拟磁盘空间布局

当然,也可以仿照FAT16文件系统,设置根目录区,其位置紧跟第2张FAT后面,大小也是固定的,这个思路相对要简单一点,请同学们自己去实现。

3.3.2 实例主要命令及函数设计

1.系统主函数main() (1)对应命令:无 (2)命令调用格式:无

- 38 -

(3)函数设计格式:void main() (4)功能:系统主函数 (5)输入:无 (6)输出:无

(7)函数需完成的工作:

① 对前面定义的全局变量进行初始化; ② 调用startsys()进入文件系统;

③ 列出文件系统提供的各项功能及命令调用格式; ④ 显示命令行提示符,等待用户输入命令; ⑤ 将用户输入的命令保存到一个buf中;

⑥ 对buf中的内容进行命令解析,并调用相应的函数执行用户键入的命令; ⑦ 如果命令不是“my_exitsys”,则命令执行完毕后转④。 2. 进入文件系统函数startsys()

(1)对应命令:无 (2)命令调用格式:无

(3)函数设计格式:void startsys()

(4)功能:由main()函数调用,进入并初始化我们所建立的文件系统,以供用户使用。 (5)输入:无 (6)输出:无。

(7)函数需完成的工作: ① 申请虚拟磁盘空间;

② 使用c语言的库函数fopen()打开myfsys文件:若文件存在,则转③;若文件不存在,则创建之,转⑤

③ 使用c语言的库函数fread()读入myfsys文件内容到用户空间中的一个缓冲区中,并判断其开始的8个字节内容是否为“10101010”(文件系统魔数),如果是,则转④;否则转⑤;

④ 将上述缓冲区中的内容复制到内存中的虚拟磁盘空间中;转⑦

⑤ 在屏幕上显示“myfsys文件系统不存在,现在开始创建文件系统”信息,并调用my_format()对①中申请到的虚拟磁盘空间进行格式化操作。转⑥;

⑥ 将虚拟磁盘中的内容保存到myfsys文件中;转⑦ ⑦ 使用c语言的库函数fclose()关闭myfsys文件;

⑧ 初始化用户打开文件表,将表项0分配给根目录文件使用,并填写根目录文件的相关信息,由于根目录没有上级目录,所以表项中的dirno和diroff分别置为5(根目录所在起始块号)和0;并将ptrcurdir指针指向该用户打开文件表项。

⑨ 将当前目录设置为根目录。

3.磁盘格式化函数my_format()

(1)对应命令:my_format (2)命令调用格式:my_format

(3)函数设计格式:void my_format()

(4)功能:对虚拟磁盘进行格式化,布局虚拟磁盘,建立根目录文件(或根目录区)。 (5)输入:无 (6)输出:无。

- 39 -

(7)函数需完成的工作:

① 将虚拟磁盘第一个块作为引导块,开始的8个字节是文件系统的魔数,记为“10101010”;在之后写入文件系统的描述信息,如FAT表大小及位置、根目录大小及位置、盘块大小、盘块数量、数据区开始位置等信息;

② 在引导块后建立两张完全一样的FAT表,用于记录文件所占据的磁盘块及管理虚拟磁盘块的分配,每个FAT占据两个磁盘块;对于每个FAT中,前面5个块设置为已分配,后面995个块设置为空闲;

③ 在第二张FAT后创建根目录文件root,将数据区的第1块(即虚拟磁盘的第6块)分配给根目录文件,在该磁盘上创建两个特殊的目录项:“.”和“..”,其内容除了文件名不同之外,其他字段完全相同。

4.更改当前目录函数my_cd()

(1)对应命令:my_cd

(2)命令调用格式:my_cd dirname

(3)函数设计格式:void my_cd(char *dirname)

(4)功能:改变当前目录到指定的名为dirname的目录。 (5)输入:

dirname:新的当前目录的目录名; (6)输出:无

(7)函数需完成的工作:

① 调用my_open()打开指定目录名的父目录文件,并调用do_read()读入该父目录文件内容到内存中;

② 在父目录文件中检查新的当前目录名是否存在,如果存在则转③,否则返回,并显示出错信息;

③ 调用my_close()关闭①中打开的父目录文件; ④ 调用my_close()关闭原当前目录文件;

⑤ 如果新的当前目录文件没有打开,则打开该目录文件;并将ptrcurdir指向该打开文件表项;

⑥ 设置当前目录为该目录。

5.创建子目录函数my_mkdir()

(1)对应命令:my_mkdir

(2)命令调用格式:my_ mkdir dirname

(3)函数设计格式:void my_mkdir(char *dirname)

(4)功能:在当前目录下创建名为dirname的子目录。 (5)输入:

dirname:新建目录的目录名。 (6)输出:无。

(7)函数需完成的工作:

① 调用do_read()读入当前目录文件内容到内存,检查当前目录下新建目录文件是否重名,若重名则返回,并显示错误信息;

② 为新建子目录文件分配一个空闲打开文件表项,如果没有空闲表项则返回-1,并显示错误信息;

③ 检查FAT是否有空闲的盘块,如有则为新建目录文件分配一个盘块,否则释放①中

- 40 -


操作系统课程设计指导书2015(8).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:计算机网络课后习题答案(仅供参考)

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: