操作系统课程设计(文件系统管理).docx
操作系统课程设计I评定等级I文件系统管理I学院计算机学院专业计算机科学与技术班级姓名学号2013年1月8日广东工业大学计算机学院制文件系统管理一、实验目的模拟文件系统的实现的基本功能,了解文件系统的基本构造和文件系统的管理方法看,加深了解文件系统的内部功能的实现。通过高级语言编写和实现一个简单的文件系统,模拟文件管理的工作过程,从而对各种文件操作系统命令的实质内容和执行过程有比较深入的了解。二、实验内容和要求编程模拟一个简单的文件系统,实现文件系统的管理和控制功能。在用户程序中通过使用文件系统提供的Creale,open,read,write,close,delete等文件命令,对文件进展操作。以下报告主要包括:1 .可行性分析2 .需求分析3 .概要设计4 .详细设计5 .测试6 .总结三、可行性分析1、技术可行性对于图形编程还不了解,但是经过本学期的三次实验的练习,可以设计好命令操作界面。利用大二期间学习的数据构造可以模拟出此课程设计的要求。2、经济可行性课程设计作为本课程的练习及进一步加深理解。与经济无关,可以不考虑。(零花费,零收益)3.法律可行性自己编写的程序,仅为练习,不作其他用途,与外界没什么联系,可行。四、需求分析编写程序实现文件系统,主要有以下几点要求:1、实现无穷级目录管理及文件管理基本操作2、实现共享“别名”3、加快了文件检索五、概要设计为了抑制单级目录所存在的缺点,可以为每一位用户建设一个单独的用户文件目录UFD(UserFileDirectory),这些文件目录可以具有相似的构造,它由用户所有文件的文件控制块组成。此外,在系统中再建设一个主文件目录MFD(MasterFileDirectory);在主文件目录中,每个用户目录文件都占有一个目录项,其目录项中包括用户名和指向该用户目录的指针。本设计主要实现下面几个数据构造:MDFUFDAFD用户名文件名翻开文件名攵祥目录指针保护码翻开保护码用户名文件长度读写指针文件目录指针文件名总体的流程图如下:六、详细设计主要数据构造:IMFD(MasterFileDirectory),主要用以存放用户,可以增加存放密码的字符数组,本设计没有保密安全方面的忧虑,为了使用时操作更简单省去密码。所以,MFD构造仅包括用户名和指向子目录的一个指针,以及指向下一用户的连接点,为线性构造。structMFD(charname20;用户名UFD*bst_pointer;文件目录指针MFD*link;1;2 .UFD(UserFileDirectory),用于存放文件的数据构造。由于本设计为了加快检索速度,使用了二叉排序树的构造,所以UFD构造中相应参加了用于树构造的ParenI,leftchild,和rightchild记录链接情况。当本文件为普通文件时,为下级记录申请AFD(file),folder为空。同样,当本文件为文件夹时,为它申请相应的空间,AFD为空。以此来到达无穷级别目录的存储。structUFDUFD *parent;UFD *leftchild;UFD *rightchild;UFD *folder;UFD *pre_fblder;AFD *file;char name30;int length;charrw;char share;char file_fblder;作为文件夹时指向下一层,文件时为空指向上一层目录(文件夹时用到)作文文件时文件的具体内容文件(夹)名字作为文件时文件的长度,默认为0读写标志1共享标志yr or wor n指示此文件是文件或文件夹,f为文件,o为文件夹1;3 .AFD,存放文件的内容的构造,比较简单,文件内容用一个字符数组存储,为顺序构造,最多可存放99个字符structAFDcharafd-file100;读指针写指针intread;intwrite;1;4.REC struct REC/UFD的线性链,用于记录共享文件和已翻开文件UFD*file;REC*link;1;登陆/创立用户查看用户关键函数说明:voidLogjn();voidInit_user();voidCheCk_uSer0;以上三个函数为开场时管理用户创立和登陆的函数。开场时没有用户,需要创立后才可登陆。创立用户即自动分配一个存放用户文件的UFD,此时的UFD为空,需要后续的创立文件以及文件夹的分配。UFD*oPerationS(UFD*fileBST);文件夹的操作调用用户登陆后即开场对该用户文件UFD的操作,同时,假设在文件夹中创立一个文件夹,它同样可以分配得到一个UFD,对用户文件的操作可以重复调用,以此来到达无穷级目录的操作。在里层文件的操作和外层的是一样的,但假设要退回外层文件夹就需要逐层返回,不能立即跳到某一层某地址。操作完毕后返回改变后的文件存储状态。void fcreate(UFD *fileBST);UFD *fdelete(UFD *fileBST);对文件夹的六个基本操作voidfopen(UFD*fileBST);voidfclose(UFD*fileBST);voidfread-write(UFD*fileBST,charf);读写操作。按选择f=5为读6为写以上五个函数为对文件的六个基本操作,其中读文件和写文件局部代码一样,所以由一个函数完成。在Create五个函数中,分别对文件夹EeBST做了相应的处理,由于删除文件的函数可能会删除到头结点,所以需要一个返回值。voidinsertBST(UFI)*fileBST,UFD*newBST);在fileBST中插入新的结点newBSTUFD*searchBST(UFD*fiieBST,charname);在fileBST树中查找名字为name的结点并返回该结点,文件不存在那么返回空voidBSTtraverse(UFD*fileBST);遍历二叉树UFD*deleteBST(UFI)*fileBST,charname30J);删除name结点,返回删除后的结点由于该设计的存储构造用到了二叉排序树,所以把相关的操作写成函数,供基本操作的函数调用。insert函数在fileBST中插入新的结点newBST;search函数在fileBST树中查找名字为name的结点并返回该结点,文件不存在那么返回空;还有traverse和delete函数对二叉排序树做了基本的操作。voidprint-path(FD*fileBST);输出当前路径voidprint_open_file();输出已翻开的文件为了在文件系统中使用户看出路径及一些相关的状态,设置了输出文件路径的函数,路径由每个文件的构造体中pre_folder记录上一层的文件夹名字,这样逐层输出即可到达目的。每执行一次操作就输出一次已翻开的文件的具体情况,翻开的文件应及时关闭,否那么删除时会有删除失败提示。UFD*check_share(charname30J);在共享链中检查是否有name文件,有那么返回该UFD,没那么NULLvoiddel_in_share(UFD*node);在共享链中删除node结点以上两个函数为对共享文件的处理函数,当翻开或读写文件时在本层文件中未找到相应的文件时,就用CheCk_share函数在共享文件中查找,如果存在就返回该文件的UFD,不存在就返回NULL,而deUkshare函数是伴随着删除文件的函数出现的,目的是为了删除文件以后不会在共享链中再存在。具体代码如下:filesysterm.hstructAFD(charafd-file100;intread;读指针intwrite;写指针1;structUFD(UFD*parent;UFD*leftchild;UFD*rightchild;UFD*folder;作为文件夹时指向下一层,文件时为空指向上一层目录(文件夹时用到)作文文件时文件的具体内容文件(夹)名字作为文件时文件的长度,默认为O读写标志ror w共享标志y or n指示此文件是文件或文件夹,f为文件,0为文件夹UFD*pre_folder;AFD3fcfile;charname30;intlength;charrw;charshare;charfile_fblder;1;structMFD(用户名文件目录指针charname20;UFD*bst_pointer;MFD*link;/UFD的线性链,用于记录共享文件和己翻开文件1;structREC(UFD*file;REC*link;登陆创立用户查看用户文件夹的操作调用,user不为空时为第一层 对文件夹的六个基本操作1;voidLogjn();voidInit_user();voidCheck_user();UFD*operations(UFD*fileBST);voidfcreate(UFD*fileBST);UFD*fdelete(UFD*fileBST);voidfopen(UFD*fileBST);代码有重复,合并读写操作。按选择s=5为新文件插入到user文件树中在fileBST树中查找名字为name的结点文件不存在那么返回空遍历二叉树删除成功返回1,失败返回0输出当前路径输出已翻开的文件在共享链中检查是否有name文件,有那么voidfclose(UFD*fileBST);voidfread_write(UFD*fileBST,charf);读6为写voidinsertBST(UFD*fileBST,UFD*newBST);UFD*searchBST(UFD*fileBST,charname);并返回该结点voidBSTtraverse(UFD*fileBST);UFD*deleteBST(UFD*fileBST,charnameL30);voidprint_path(UFD*fileBST);voidprint_open_file();UFD*check_share(charnamel30);在共享链中删除node结点返回UFD,没那么NULLvoiddel_in_share(UFD*node);main.cpp#include<iostream>#include<conio.h>#include"filesystem.h"MFD *mfdink=NULL;MFD *pre_user;UFD *pre_opera_folder=NULL;int folder_depth=0;REC *share.file=NULL;REC *open_file=NULL;void PrinLPath(UFD *fileBST)用户链表当前操作用户当前操作文件夹记录当前文件深度(用于辅助pre-folder的初始化)输出路径if(fileBST->pre-folder!=NULL)(print_path(fiIeBST->pre-folder);printf(17%s,fileBST->pre-folder->name);elseprintf(,7%s",pre-user->name);)voidprint_open_file()(REC*temp;inti=5;temp=open_file;while(temp!=NULL)(printf("%st%dtt',temp->file->name,temp->file->length);if(temp->file->rw=T)printf("只读t");elsePrintf("可读写t");if(temp>We>Share='y')printf("是t");elsePrintf("否t");for(i=0;i<5;i+)(if(temp->file->file->afd-filei!=,O')printf(',%c",temp->file->file->afd-fileli);elsebreak;1if(temp->file->file->afd-filei!='0,<fe<fci=5)printf(".");printf("n);temp=temp->link;1)voidBSTtraverse(UFD*fileBST)遍历二叉树(前序遍历)UFD*lef*right;Printf("%s",fileBSF>name);if(fileBST->file-folder='o')输出.以区分文件夹printf(".t");elseprintf("f');if(fileBST->leftchild!=NULL)/递归(left=fileBST->leftchild;BSTtraverse(Ieft);)if(fileBST->rightchild!=NULL)(right=fileBST->rightchild;BSTtraverse(right);1)UFD*searchBST(UFD*fileBST,charname30)fileBST树中查找名字为name的结点并返回该结点(文件不存在那么返回空intflag;flag=strcmp(fileBS,P>name,name);if(flag=O)returnfileBST;查找成功elseif(f)ag>O)(if(fileBST->leftchild=NULL)returnNULL;查找失败elsesearchBST(fileBST->leftchild,name);递归调用1else(if(fileBST->rightchild=NULL)returnNULL;elsesearchBST(fileBST->rightchild,name);1)voidinsertBST(UFD*fileBST,UFD*newBST)将结点newBST插入原二叉树fileBST中(intflag;flag=strcmp(fileBSTL>name,newBST->name);if(flag>O)(if(fileBST->leftchild=NULL)插入(fileBST->leftchild=newBST;newBST->parent=fileBST;elseinsertBST(fileBST->leftchild,newBST);递归调用1else(if(fileBSl1>rightchild=NULL)插入(fileBST->rightchild=newBST;newBST->parent=fileBST;)elseinsertBST(fileBST->rightchild,newBST);递归调用1*flag=O的情况已在创立时排除*/)UFD*deleteBST(UFD*fileBST,charname30)删除名字问name的文件结点(UFD*parenLfHe=NULL,*deLfne=NULL;UFD*move_file=NULL,*move_file_parent;del_file=searchBST(fileBST,name);if(del_file=NULL)(Printf("没有此文件,删除失败!n,);getch();returnfileBST;查找失败)if(deLfile->file-folder=,o'<fc<festrcmp(deLfile->folder->name,"NULL")!=0)Primf("注意,本系统未能实现级联删除,请先逐个删除文件!”);Printf("文件夹非空,删除失败!n");getch();returnfileBST;)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");elseif(parent_file->leftchild=del_file)parent-file->leftchild=NULL;free(del_file);)else(parent-file->rightchild=NULL;free(del_file);)1elseif(del-file->leftchild=NULLdel-file->rightchild=NULL)被删除结点没有做孩子或右孩子(if(del-file->leftchild=NULL)没有左孩子1if(parent_file=NULL)删除的为根结点(fileBST=del-file->rightchild;del_file->rightchild->parent=NULL;)elseif(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;)elseif(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;)elseif(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;)else(while(move_file->rightchild!=NULL)寻找右边最底下的结点(move_file=move_file->rightchild;move_file_parent=move_file_parent->rightchild;)move_file_parent->rightchild=NULL;move_file->Ieftchild=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=deLfile)删除的为根结点fileBST=move_file;free(del_file);Printf("成功删除文件sn",name);getch();returnfileBST;)voiddel_in_share(UFD*node)(REC*first,*second;first=share_file;second=share_file->link;if(second=NULL)share_file=NULL;free(first);)elsedo(if(second->file=node)first->link=second->linkfree(second);)else(first=first->link;second=second->link;)while(second!=NULL);)voidfcreate(UFD*fileBST)在fileBST的同一层创立文件(chars;charname30;intflag=0;UFD*newfile,*temp=NULL;REC*stemp;system("cls,');printf("n,);printf("文件系统/创建文件nH);printf("nn");doprintf("1.创立文件n");printf("2.创立文件夹n");printf(,3.取消n");Printf("请选择:n');scanf(n%c'&s);fflush(stdin);if(s=-3')return;if(s!=T&&s!=2)Printf("输入错误,请重新输入!n");while(s!=T&&s!=2);if(strcmp(fileBST->name,NULL")=O)节点已有(未赋值)用于本层文件夹的第一个文件的特殊情况newfile=fileBST;else(newfile=(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");SlrCPy(newfile->name,"NULL");return;1strcpy(newfile->name,name);if(folder_depth=1)newfile->pre-folder=NULL;elsenewfile->pre_folder=pre_opera_folder;指向正在操作文件夹while(l)读写否,共享否(Printfd只读r还是可读写w:");scanf(1,%c'<fe(newfile->rw);fflush(stdin);Printf("是否共享y/n:");scanf(1,%c'<fe(newfile->share);fflush(stdin);if(newfile->rw='r'newfile->rw=-w')&&(newfile->share=y|newfile->share='n')break;Printf("输入有误,请重新输入!nn);)*以下为文件和文件夹初始化中不同的地方*if(s=')newfile->file-folder='f;newfile->folder=NULL;newfile->file=(AFD*)malloc(sizeof(AFD);Printfd请输入文件的内容(<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=O;newfile->folder=(UFD*)malloc(sizeof(UFD);/连上一个空文件节点newfile->fblder->pre-folder=newfile;newfile->folder->leftchild=NULL;strcpy(newfile->folder->name,"NULLH);newfile->fblder->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;ShareStemp;)UFD*fdelete(UFD*fileBST)在fileBST的同一层删除文件(charname30J;REC*temp;Printf("请输入要删除的文件:”);scanf(',%s",name);fflush(stdin);temp=叩检查文件是否翻开,翻开那么删除失败while(temp!=NULL)(if(strcmp(temp->file->name,name)=O)Printf("文件翻开中,请关闭后再删除!");getch();returnfileBST;elsetemp=temp->link;1fileBST=deleteBST(fileBST,name);returnfileBST;)voidfopen(UFD*fileBST)(charname30J;UFD*temp=NULL,*tempI=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_fblder=temp;temp->flder=operations(temp->folder);pre_opera_fblder=temp1;写回folder-depth"1else翻开文件REC*newopen;newopen=(REC*)malloc(sizeof(REC);接入翻开链newopen->file=temp;newopen->link=open-file;open_file=newopen;Printf("已成功翻开问s!n",temp->name);getch();voidfclose()(charname30;REC*first=NULL,*second=NULL;Printf(”请输入要关闭的文件:”);scanf(',%s",name);fflush(stdin);first=open_file;if(first=NULL)(Prindr没有翻开的文件n");getch();return;)elsesecond=first->link;if(second=NULL&&strcmp(first->file->name,name)=0)(free(first);open_file=NULL;Printf("成功关闭文件sn!",name);return;1else(While(Secondl=NULL)(if(strcmp(second->flle->name,name)=0)(first->link=second->link;free(second);Printf("成功关闭文件sn!",name);return;)else(first=first->link;second=second->link;)1Printf("没有找到问件s,关闭失败!n'name);)voidfread_write(UFD*fileBST,charf)(chars;charname30J;charnewfile100;UFD*temp=NULL;if(f=5,)Printf("请输入要读取的文件的名字:”);elsePrindr请输入要写入的文件的名字:");scanf(',%s",name);fflush(stdin);temp=searchBST(fileBST,name);if(temp=NULL)(Printf("文件不存在!n,);temp=check_share(name);if(temp=NULL)Printf("文件不存在!n");return;)1if(temp->file.folder='o,)(Printfd文件夹不可读写!");return;1Printf("文件的内容是:%snnn",temp->file->afd-file);getch();if(f='5')return;读取文件操作到此完毕if(temp->rw='r')(Printf("只读文件,不可写入!n);return;1else追加或重写(do(SyStem("cls");printf("1.追加n");printfC,2.重写n);printf('r3.取消n"):Printf("请选择:11h);scanf(',%c,s);fflush(stdin);if(s=,3')return;if(s!=T&&s!=2)Printf("输入错误,请重新输入!n");)while(s!='<fc<fcs!=,2,);Primf(”请输入要重写或追加的内容(<100):,1);scanf(',%s",newfile);修改fflush(stdin);if(s=,)strcat(temp->file->af<i-file,newfile);elsestrcpy(temp->file->afd-file,newfile);temp->length=strlen(temp->file->afd-file);UFD*check_share(charname30J)(chars;UFD*temp=NULL;REC*stemp=NULL;Printf(”共享文件夹为:n");stemp=share_file;While(Stempl=NULL)printf("%s',stemp->file->name);if(stemp->file->file-folder="f)printf("t");elseprintf(".t,');stemp=stemp->link;printf("n是否尝试在共享文件夹中翻开(y/n):");dos=getchar();if(s=-n,s=-N,)returnNULL;elseif(s="y's=-Y')break;elseprintf("输入错误,请重新输入:");while(s!='y'&&s!='n'&&s!='Y'&&s!='N');stemp=share_file;While(Stempl=NULL)(if(strcmp(stemp->file->name,name)=O)temp=stemp->file;break;stemp=stemp->link;1returntemp;)UFD*operations(UFD*fileBST)while(l)chars;system("cls");if(open_file!=NULL)(Printf(”已翻开文件,请及时关闭!n);Printf("文件名t文件长度t读写t共享t内容”);printf("