操作系统课程设计(文件系统管理)文件.doc
评定等级操作系统课程设计文件系统管理学 院 计算机学院专 业 计算机科学与技术班 级姓 名学 号2013 年 1 月 8 日广东工业大学计算机学院制文件系统管理一、实验目的模拟文件系统的实现的基本功能,了解文件系统的基本结构和文件系统的管理方法看,加深了解文件系统的内部功能的实现。 通过高级语言编写和实现一个简单的文件系统, 模拟文件管理的工作过程, 从而对各种文件操作系统命令的实质内容和执行过程有比较深入的了解。二、实验内容和要求编程模拟一个简单的文件系统, 实现文件系统的管理和控制功能。 在用户程序中通过使用文件系统提供的 create,open,read,write,close,delete 等文件命令,对文件进行操作。以下报告主要包括:1.可行性分析2.需求分析3.概要设计4.详细设计5.测试6.总结三、可行性分析1、技术可行性对于图形编程还不了解, 但是经过本学期的三次实验的练习, 可以设计好命令操作界面。 利用大二期间学习的数据结构可以模拟出此课程设计的要求。2、经济可行性课程设计作为本课程的练习及进一步加深理解。与经济无关,可以不考虑。 (零花费,零收益)3.法律可行性自己编写的程序,仅为练习,不作其他用途,与外界没什么联系,可行。四、需求分析编写程序实现文件系统,主要有以下几点要求:1、实现无穷级目录管理及文件管理基本操作2、实现共享“别名”3、加快了文件检索五、概要设计为了克服单级目录所存在的缺点,可以为每一位用户建立一个单独的用户文件目录UFD (User File Directory )。这些文件目录可以具有相似的结构,它由用户所有文件的文件控制块组成。此外,在系统中再建立一个主文件目录 MFD (Master File Directory );在主文件目录中, 每个用户目录文件都占有一个目录项, 其目录项中包括用户名和指向该用户目录的指针。本设计主要实现下面几个数据结构:M D F U F D A F D用户名 文件名 打开文件名文件目录指针 保护码 打开保护码用户名 文件长度 读写指针文件目录指针 文件名···总体的流程图如下:六、详细设计主要数据结构:1.MFD (Master File Directory ),主要用以存放用户,可以增加存放密码的字符数组,本设计没有保密安全方面的忧虑,为了使用时操作更简单省去密码。所以, MFD 结构仅包括用户名和指向子目录的一个指针,以及指向下一用户的连接点,为线性结构。struct MFDchar name20; /用户名UFD *bst_pointer; /文件目录指针MFD *link;2. UFD (User File Directory ),用于存放文件的数据结构。由于本设计为了加快检索速度,使用了二叉排序树的结构,所以 UFD 结构中相应加入了用于树结构的 parent,leftchild ,和rightchild 记录链接情况。当本文件为普通文件时,为下级记录申请 AFD (file ),folder 为空。同样,当本文件为文件夹时,为它申请相应的空间, AFD 为空。以此来达到无穷级别目录的存储。struct UFDUFD *parent;UFD *leftchild;UFD *rightchild;UFD *folder; /作为文件夹时指向下一层,文件时为空UFD *pre_folder; /指向上一层目录(文件夹时用到)AFD *file; /作文文件时文件的具体内容char name30; /文件(夹)名字int length; /作为文件时文件的长度,默认为 0char rw; /读写标志 r or wchar share; /共享标志 y or nchar file_folder; /指示此文件是文件或文件夹, f 为文件, o 为文件夹;3.AFD ,存放文件的内容的结构,比较简单,文件内容用一个字符数组存储,为顺序结构,最多可存放 99 个字符struct AFDchar afd_file100;int read; /读指针int write; /写指针;4.RECstruct REC /UFD 的线性链,用于记录共享文件和已打开文件UFD *file;REC *link;关键函数说明:void Log_in(); /登陆void Init_user(); /创建用户void Check_user(); /查看用户以上三个函数为开始时管理用户创建和登陆的函数。 开始时没有用户, 需要创建后才可登陆。创建用户即自动分配一个存放用户文件的 UFD ,此时的 UFD 为空,需要后续的创建文件以及文件夹的分配。UFD *operations(UFD *fileBST); /文件夹的操作调用用户登陆后即开始对该用户文件 UFD 的操作,同时,若在文件夹中创建一个文件夹,它同样可以分配得到一个 UFD ,对用户文件的操作可以重复调用,以此来达到无穷级目录的操作。 在里层文件的操作和外层的是一样的, 但若要退回外层文件夹就需要逐层返回, 不能立即跳到某一层某地址。操作完毕后返回改变后的文件存储状态。void fcreate(UFD *fileBST); /对文件夹的六个基本操作UFD *fdelete(UFD *fileBST);void fopen(UFD *fileBST);void fclose(UFD *fileBST);void fread_write(UFD *fileBST,char f); /读写操作。按选择 f=5 为读 6 为写以上五个函数为对文件的六个基本操作, 其中读文件和写文件部分代码相同, 所以由一个函数完成。在 create五个函数中,分别对文件夹 fileBST 做了相应的处理,由于删除文件的函数可能会删除到头结点,所以需要一个返回值。void insertBST(UFD *fileBST,UFD *newBST); /在 fileBST 中插入新的结点 newBSTUFD *searchBST(UFD *fileBST,char name); /在 fileBST 树中查找名字为 name 的结/点并返回该结点,文件不存在则返回空void BSTtraverse(UFD *fileBST); /遍历二叉树UFD *deleteBST(UFD *fileBST,char name30); /删除 name 结点,返回删除后的结点由于该设计的存储结构用到了二叉排序树, 所以把相关的操作写成函数, 供基本操作的函数调用。 insert 函数在 fileBST 中插入新的结点 newBST;search 函数在 fileBST 树中查找名字为 name 的结点并返回该结点,文件不存在则返回空;还有 traverse 和 delete 函数对二叉排序树做了基本的操作。void print_path(UFD *fileBST); /输出当前路径void print_open_file(); /输出已打开的文件为了在文件系统中使用户看出路径及一些相关的状态, 设置了输出文件路径的函数, 路径由每个文件的结构体中 pre_folder 记录上一层的文件夹名字, 这样逐层输出即可达到目的。每执行一次操作就输出一次已打开的文件的具体情况, 打开的文件应及时关闭, 否则删除时会有删除失败提示。UFD *check_share(char name30); /在共享链中检查是否有 name 文件,有则/返回该 UFD ,没则 NULLvoid del_in_share(UFD *node); /在共享链中删除 node 结点以上两个函数为对共享文件的处理函数, 当打开或读写文件时在本层文件中未找到相应的文件时,就用 check_share 函数在共享文件中查找,如果存在就返回该文件的 UFD,不存在就返回 NULL ,而 del_in_share 函数是伴随着删除文件的函数出现的,目的是为了删除文件以后不会在共享链中再存在。具体代码如下:filesysterm.hstruct AFDchar afd_file100;int read; /读指针int write; /写指针;struct UFDUFD *parent;UFD *leftchild;UFD *rightchild;UFD *folder; /作为文件夹时指向下一层,文件时为空UFD *pre_folder; /指向上一层目录(文件夹时用到)AFD *file; /作文文件时文件的具体内容char name30; /文件(夹)名字int length; /作为文件时文件的长度,默认为 0char rw; /读写标志 r or wchar share; /共享标志 y or nchar file_folder; /指示此文件是文件或文件夹, f 为文件, o 为文件夹;struct MFDchar name20; /用户名UFD *bst_pointer; /文件目录指针MFD *link;struct REC /UFD 的线性链,用于记录共享文件和已打开文件UFD *file;REC *link;void Log_in(); /登陆void Init_user(); /创建用户void Check_user(); /查看用户UFD *operations(UFD *fileBST); /文件夹的操作调用, user 不为空时为第一层void fcreate(UFD *fileBST); /对文件夹的六个基本操作UFD *fdelete(UFD *fileBST);void fopen(UFD *fileBST);void fclose(UFD *fileBST);void fread_write(UFD *fileBST,char f); /代码有重复,合并读写操作。按选择 s=5 为读 6 为写void insertBST(UFD *fileBST,UFD *newBST); /新文件插入到 user 文件树中UFD *searchBST(UFD *fileBST,char name); /在 fileBST 树中查找名字为 name 的结点并返回该结点/文件不存在则返回空void BSTtraverse(UFD *fileBST); /遍历二叉树UFD *deleteBST(UFD *fileBST,char name30); /删除成功返回 1,失败返回 0void print_path(UFD *fileBST); /输出当前路径void print_open_file(); /输出已打开的文件UFD *check_share(char name30); /在共享链中检查是否有 name 文件,有则返回 UFD ,没则 NULLvoid del_in_share(UFD *node); /在共享链中删除 node 结点main.cpp#include <iostream>#include<conio.h>#include"filesystem.h"MFD *mfd_link=NULL; /用户链表MFD *pre_user; /当前操作用户UFD *pre_opera_folder=NULL; /当前操作文件夹int folder_depth=0; /记录当前文件深度(用于辅助 pre_folder 的初始化)REC *share_file=NULL;REC *open_file=NULL;void print_path(UFD *fileBST) /输出路径if(fileBST->pre_folder!=NULL) print_path(fileBST->pre_folder);printf("/%s",fileBST->pre_folder->name);elseprintf("/%s",pre_user->name);void print_open_file()REC *temp;int i=5;temp=open_file;while(temp!=NULL)printf("%st%dtt",temp->file->name,temp->file->length);if(temp->file->rw='r')printf(" 只读t");else printf(" 可读写 t");if(temp->file->share='y')printf(" 是t");else printf(" 否t");for(i=0;i<5;i+)if(temp->file->file->afd_filei!='0')printf("%c",temp->file->file->afd_filei);else break;if(temp->file->file->afd_filei!='0'&&i=5) printf(".");printf("n");temp=temp->link;void BSTtraverse(UFD *fileBST) /遍历二叉树(前序遍历)UFD *left,*right;printf("%s",fileBST->name);if(fileBST->file_folder='o') /输出 .以区分文件夹printf(".t");elseprintf("t");if(fileBST->leftchild!=NULL) /递归left=fileBST->leftchild;BSTtraverse(left);if(fileBST->rightchild!=NULL)right=fileBST->rightchild;BSTtraverse(right);UFD *searchBST(UFD *fileBST,char name30)/ 在 fileBST 树中查找名字为 name 的结点并返回该结点 /文件不存在则返回空int flag;flag=strcmp(fileBST->name,name);if(flag=0)return fileBST; /查找成功else if(flag>0)if(fileBST->leftchild=NULL) return NULL; /查找失败elsesearchBST(fileBST->leftchild,name); /递归调用elseif(fileBST->rightchild=NULL) return NULL;elsesearchBST(fileBST->rightchild,name);void insertBST(UFD *fileBST,UFD *newBST) / 将结点 newBST 插入原二叉树fileBST 中int flag;flag=strcmp(fileBST->name,newBST->name);if(flag>0)if(fileBST->leftchild=NULL) /插入fileBST->leftchild=newBST;newBST->parent=fileBST;elseinsertBST(fileBST->leftchild,newBST); /递归调用elseif(fileBST->rightchild=NULL) /插入fileBST->rightchild=newBST;newBST->parent=fileBST;elseinsertBST(fileBST->rightchild,newBST); /递归调用/*flag=0 的情况已在创建时排除 */UFD *deleteBST(UFD *fileBST,char name30)/ 删除名字问 name 的文件结点UFD *parent_file=NULL,*del_file=NULL;UFD *move_file=NULL,*move_file_parent;del_file=searchBST(fileBST,name);if(del_file=NULL)printf(" 没有此文件,删除失败! n");getch();return fileBST; /查找失败if(del_file->file_folder='o'&&strcmp(del_file->folder->name,"NULL")!=0) printf(" 注意,本系统未能实现级联删除,请先逐个删除文件! ");printf(" 文件夹非空,删除失败! n");getch();return fileBST;if(del_file->share='y') /先在共享链中删除del_in_share(del_file);parent_file=del_file->parent;if(del_file->leftchild=NULL&&del_file->rightchild=NULL) / 被删除结点为子叶结点if(del_file=fileBST) /只有一个结点strcpy(fileBST->name,"NULL");else if(parent_file->leftchild=del_file)parent_file->leftchild=NULL;free(del_file);elseparent_file->rightchild=NULL;free(del_file);else if(del_file->leftchild=NULL|del_file->rightchild=NULL) /被删除结点没有做孩子或右孩子if(del_file->leftchild=NULL) /没有左孩子if(parent_file=NULL) /删除的为根结点fileBST=del_file->rightchild;del_file->rightchild->parent=NULL;else if(parent_file->leftchild=del_file) /右孩子接上parent_file->leftchild=del_file->rightchild;del_file->rightchild->parent=parent_file;else /右孩子接上parent_file->rightchild=del_file->rightchild;del_file->rightchild->parent=parent_file;else /没有右孩子if(parent_file=NULL) /删除的为根结点fileBST=del_file->leftchild;del_file->leftchild->parent=NULL;else if(parent_file->leftchild=del_file) /左孩子接上parent_file->leftchild=del_file->leftchild;del_file->leftchild->parent=parent_file;else /左孩子接上parent_file->rightchild=del_file->leftchild;del_file->leftchild->parent=parent_file;free(del_file);else /左右孩子都有move_file_parent=del_file->leftchild;move_file=move_file_parent->rightchild;if(move_file=NULL) /被删除结点的左孩子没有右孩子if(parent_file=NULL) /删除的为根结点fileBST=move_file_parent;fileBST->rightchild=del_file->rightchild;fileBST->parent=NULL;else if(parent_file->leftchild=del_file)parent_file->leftchild=move_file_parent;elseparent_file->rightchild=move_file_parent;move_file_parent->parent=parent_file;move_file_parent->rightchild=del_file->rightchild;elsewhile(move_file->rightchild!=NULL) /寻找右边最底下的结点move_file=move_file->rightchild;move_file_parent=move_file_parent->rightchild;move_file_parent->rightchild=NULL;move_file->leftchild=del_file->leftchild;move_file->rightchild=del_file->rightchild;if(move_file->rightchild!=NULL)move_file->rightchild->parent=move_file; /右孩子的双亲也要改变move_file->parent=del_file->parent;if(fileBST=del_file) /删除的为根结点fileBST=move_file;free(del_file);printf(" 成功删除文件 %sn",name);getch();return fileBST;void del_in_share(UFD *node)REC *first,*second;first=share_file;second=share_file->link;if(second=NULL)share_file=NULL;free(first);elsedoif(second->file=node)first->link=second->link;free(second);elsefirst=first->link;second=second->link;while(second!=NULL);void fcreate(UFD *fileBST) /在 fileBST 的同一层创建文件char s;char name30;int flag=0;UFD *newfile,*temp=NULL;REC *stemp;system("cls");printf("-n");printf("- 文 件 系 统/创 建 文 件-n");printf("-nn");doprintf(" 1. 创建文件 n");printf(" 2. 创建文件夹 n");printf(" 3. 取消 n");printf(" 请选择: n");scanf("%c",&s);fflush(stdin);if(s='3')return;if(s!='1'&&s!='2')printf(" 输入错误,请重新输入! n");while(s!='1'&&s!='2');if(strcmp(fileBST->name,"NULL")=0) /节点已有(未赋值)用于本层文件夹的第一个文件的特殊情况newfile=fileBST;elsenewfile=(UFD*)malloc(sizeof(UFD); /创建树节点newfile->leftchild=NULL;newfile->rightchild=NULL;printf(" 请输入文件(夹)名: ");scanf("%s",name);fflush(stdin);/搜索二叉树,文件重名就创建失败temp=searchBST(fileBST,name);if(temp!=NULL)printf(" 已存在该文件(夹) ,创建失败! n");strcpy(newfile->name,"NULL");return;strcpy(newfile->name,name);if(folder_depth=1)newfile->pre_folder=NULL;elsenewfile->pre_folder=pre_opera_folder;/ 指向正在操作文件夹while(1) /读写否,共享否printf(" 只读 r 还是可读写 w:");scanf("%c",&(newfile->rw);fflush(stdin);printf(" 是否共享 y/n:");scanf("%c",&(newfile->share);fflush(stdin);if(newfile->rw='r'|newfile->rw='w')&&(newfile->share='y'|newfile->share='n')break;printf(" 输入有误,请重新输入! n");/* 以下为文件和文件夹初始化中不同的地方 *if(s='1')newfile->file_folder='f'newfile->folder=NULL;newfile->file=(AFD*)malloc(sizeof(AFD);printf(" 请输入文件的内容( <100):");scanf("%s",newfile->file->afd_file);fflush(stdin);newfile->length=strlen(newfile->file->afd_file);else /文件夹的初始化newfile->file_folder='o'newfile->file=NULL;newfile->length=0;newfile->folder=(UFD*)malloc(sizeof(UFD); /连上一个空文件节点newfile->folder->pre_folder=newfile;newfile->folder->leftchild=NULL;strcpy(newfile->folder->name,"NULL");newfile->folder->rightchild=NULL;/*if(fileBST!=newfile)insertBST(fileBST,newfile); / 初始化完成后插入到二叉树中elsenewfile->parent=NULL;/ 第一个结点略去插入,其双亲结点为空if(newfile->share='y') /接入共享链stemp=(REC*)malloc(sizeof(REC);stemp->file=newfile;stemp->link=share_file;share_file=stemp;UFD *fdelete(UFD *fileBST) /在 fileBST 的同一层删除文件char name30;REC *temp;printf(" 请输入要删除的文件: ");scanf("%s",name);fflush(stdin);temp=open_file; /检查文件是否打开,打开则删除失败while(temp!=NULL)if(strcmp(temp->file->name,name)=0) printf(" 文件打开中,请关闭后再删除! ");getch();return fileBST;else temp=temp->link;fileBST=deleteBST(fileBST,name);return fileBST;void fopen(UFD *fileBST)char name30;UFD *temp=NULL,*temp1=NULL;printf(" 请输入要打开的文件的名字: ");scanf("%s",name);fflush(stdin);temp=searchBST(fileBST,name);if(temp=NULL)printf(" 文件不存在! n");temp=check_share(name);if(temp=NULL) printf(" 文件不存在! n");return;/* 找到文件,以下为打开部分 *if(temp->file_folder='o') /打开文件夹folder_depth+;temp1=pre_opera_folder; /保护正在操作文件pre_opera_folder=temp;temp->folder=operations(temp->folder);pre_opera_folder=temp1; /写回folder_depth-;else /打开文件REC *newopen;newopen=(REC*)malloc(sizeof(REC);/ 接入打开链newopen->file=temp;newopen->link=open_file;open_file=newopen;printf(" 已成功打开问 %s!n",temp->name);getch();void fclose()char name30;REC *first=NULL,*second=NULL;printf(" 请输入要关闭的文件: ");scanf("%s",name);fflush(stdin);first=open_file;if(first=NULL)printf(" 没有打开的文件 n");getch();return;else second=first->link;if(second=NULL&&strcmp(first->file->name,name)=0)free(first); open_file=NULL;printf(" 成功关闭文件 %sn!",name);return;elsewhile(second!=NULL)if(strcmp(second->file->name,name)=0)first->link=second->link; free(second);printf(" 成功关闭文件 %sn!",name);return;elsefirst=first->link;second=second->link;printf(" 没有找到问件 %s,关闭失败! n",name);void fread_write(UFD *fileBST,char f)char s;char name30;char newfile100;UFD *temp=NULL;if(f='5')printf(" 请输入要读取的文件的名字: ");elseprintf(" 请输入要写入的文件的名字: ");scanf("%s",name);fflush(stdin);temp=searchBST(fileBST,name);if(temp=NULL)printf(" 文件不存在! n");temp=check_share(name);if(temp=NULL) printf(" 文件不存在! n");return;if(temp->file_folder='o')printf(" 文件夹不可读写! ");return;printf(" 文件的内容是: %snnn",temp->file->afd_file);getch();if(f='5')return; /读取文件操作到此结束if(temp->rw='r')printf(" 只读文件,不可写入! n");return;else /追加或重写dosystem("cls");