还剩31页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
操作系统课程设计报告小组编号小组成员
一、课程设计概述、题目简单文件系统的实现
1、实现内容2在内存中开辟一个虚拟磁盘空间作为文件存储分区,在其上实现一个简单的基于多级目1录的单用户单任务系统中的文件系统在退出该文件系统的使用时,应将该虚拟文件系统以一个文件的方式保存到磁盘上,以便下次可以再将它恢复到内存的虚拟磁盘空间中Windows文件存储空间的分配可采用显式链接分配或其他的办法2空闲磁盘空间的管理可选择位示图或其他的办法如果采用位示图来管理文件存储空间,3并采用显式链接分配方式,那么可以将位示图合并到中FAT文件目录结构采用多级目录结构为了简单起见,可以不使用索引结点,其中的每个目4录项应包含文件名、物理地址、长度等信息,还可以通过目录项实现对文件的读和写的保护要求提供以下操作命令5对文件存储器进行格式化,即按照文件系统的结构对虚拟磁盘空间进•my.format行布局,并在其上创建根目录以及用于管理文件存储空间等的数据结构用于创建子目录•my_mkdir用于删除子目录•my_rmdir用于显示目录中的内容•myjs用于更改当前目录•my_cd用于创建文件•my_create用于打开文件•my_open用于关闭文件•my_close用于写文件•my_write用于读文件•my_read用于删除文件•my_rm用于退出文件系统•my_exitsys
二、设计思路主要算法描述、程序流程图等:系统主函数
1.main对应命令无1命令调用格式无2函数设计格式3void main功能系统主函数4输入无5输出无6函数需完成的工作7
①对前面定义的全局变量进行初始化;
②调用进入文件系统;startsys//磁盘块大小#define BLOCKSIZE1024//虚拟磁盘空间大小#define SIZE1024000中的文件结束标志#define END65535//FAT中盘块空闲标志#define FREE0//FAT〃根目录区所占盘块数#define ROOTBLOCKNUM2//最多同时打开文件个数#define MAXOPENFILE10t#define MAXTEXT10000/*文件控制块*/typedef structFCB{//文件名char niename
[8];//文件扩展名char exname
[3];//文件属性字段,值为时表示目录文件,值为时表示数据文unsigned charattribute;01件//文件创建时间unsigned shorttime;//文件创建日期unsigned shortdate;//文件起始盘块号unsigned shortfirst;//文件长度unsigned longlength;〃表示目录项是否为空,若值为表示空,值为表示已分配char free;0,1,}fcb;/*文件分配表刃typedef structFAT(〃磁盘块的状态(空闲的,最后的,下一个)unsigned shortid;}fat;/*用户打开文件表*/typedef structUSEROPEN(//文件名char filename
[8];//文件扩展名char exname
[3];〃文件属性字段,值为时表示目录文件,值为时表示数据文件unsigned charattribute;01//文件创建时间unsigned shorttime;//文件创建日期unsigned shortdate;//文件起始盘块号unsigned shortfirst;〃文件长度(对数据文件是字节数,对目录文件可以是目录项个数)unsigned longlength;〃表示目录项是否为空,若值为表示空,值为表示已分配char free;0,1,//相应打开文件的目录项在父目录文件中的盘块号unsigned shortdirno;//相应打开文件的目录项在父目录文件的盘块中的目录项序号int diroff;dirno〃相应打开文件所在的路径名,这样方便快速检查出指定文件是否已经char dir
[80];打开//父目录在打开文件表项的位置int father;〃读写指针在文件中的位置,文件的总字符数int count;〃是否修改了文件的的内容,如果修改了置为否则为char fcbstate;FCB1,0//表示该用户打开表项是否为空,若值为表示为空,否则表示已被某打char topenfile;0,开文件占据Juseropen;/*引导块*/typedef structBLOCKO//文件系统魔数char magic
[10];〃存储一些描述信息,如磁盘块大小、磁盘块数量、最多打开文件char information
[200];数等〃根目录文件的起始盘块号unsigned shortroot;//虚拟磁盘上数据区开始位置unsigned char*startblock;JblockO;//指向虚拟磁盘的起始地址unsigned char*myvhard;//用户打开文件表数组useropen openfilelist[MAXOPENFILE];//用户打开文件表中的当前目录所在打开文件表项的位置int curdir;//记录当前目录的目录名包括目录的路径char currentdir
[80];//记录虚拟磁盘上数据区开始位置unsigned char*startp;〃文件系统的文件名char myfilename[]=myEesys”;//进入文件系统void startsys;//磁盘格式化void my_format;//更改当前目录void my_cdchar*dirname;//创建子目录void my_mkdirchar*dirname;//删除子目录void my_rmdirchar*dirname;//显示目录void my_ls;//创建文件void my_create char*filename;//删除文件void my_rmchar*filename;//打开文件int my_openchar*filename;//关闭文件int my_closeint fd;//写文件int my_writeint fd;//实际写文件int do_writeint fd,char int len,char wstyle;//读文件int my_read int fd,int len;//实际读文件int do_read int fd,int len,char*text;//退出文件系统void my_exitsys;//寻找空闲盘块unsigned short findblock;//寻找空闲文件表项int findopenfile;void startsysFILE*fp;unsigned charbuf[SIZE];fcb*root;int i;〃申请虚拟磁盘空间myvhard=unsigned char*mallocSIZE;〃将中前个字节用替换并返回memsetmyvhard,0,SIZE;myvhard SIZE0myvhard iffp=fopenmyfilename,nrn!=NULL〃将二进制文件读取到缓冲区freadbuf,SIZE,1,fp;fclosefp;ifstrcmpblockO*buf-magic,n10101010n printfHmyfilesys is not exist,begin tocreat the file...\nH;my_format;}else fori=0;i SIZE;i++myvhard[i]=buffi];}elseprintf**my filesysis not exist,begin tocreat the file…my_format;root=fcb*myvhard+5*BLOCKSIZE;strcpyopenfilelist
[0].filename,root-filename;strcpyopenfilelist
[0].exname,root-exname;openfilelist
[0].attribute=root-attribute;openfilelist
[0].time=root-time;openfilelist
[0].date=root-date;openfilelist
[0].first=root-first;openfileIist
[0]Jength=root-length;openfilelist
[0].free=root-free;openfilelist
[0].dirno=5;openfilelist
[0].diroff=0;strcpyopenfilelist
[0].dir H\\root\\n;9openfilelist
[0].father=0;openfilelist
[0].count=0;openfilelist
[0].fcbstate=0;openfilelist
[0].topenfile=1;fori=l;i MAXOPENFILE;i++openfilelist[i].topenfile=0;curdir=0;strcpycurrentdir,n\\root\\n;startp=blockO*myvhard-startblock;}void my_format FILE*fp;fat*fat2;blockO*blkO;time_t now;struct tm*nowtime;fcb*root;int i;blkO=blockO*myvhard;fatl=fat*myvhard+BLOCKSIZE;fat2=fat*myvhard+3*BLOCKSIZE;root=fcb*myvhard+5*BLOCKSIZE;strcpyblkO-magic,n10101010H;strcpyblkO-information,My FileSystemVer
1.0\n Blocksize=lKB Wholesize=1000KBBlocknum=1000RootBlocknum=2\nn;blkO-root=5;blkO-startblock=unsigned char*root;fori=0;i5;i++{fatl-id=END;fat2-id=END;fatl++;fat2++;fatl-id=6;fat2-id=6;fatl++;fat2++;fatl-id=END;fat2-id=END;fatl++;fat2++;fori=7;i SIZE/BLOCKSIZE;i++fatl-id=FREE;fat2-id=FREE;fatl++;fat2++;}now=timeNULL;nowtime=localtimenow;strcpyroot-filename,n.n;strcpyroot-exname,nH;root-attribute=0x28;root-time=nowtime-tm_hour*2048+nowtime-tm_min*32+nowtime-tm_sec/2;root-date=nowtime-tm_year-80*512+nowtime-tm_mon+1*32+nowtime-tm_mday;root-first=5;root-length=2*sizeoffcb;root-free=1;root++;now=timeNULL;nowtime=localtimenow;strcpyroot-filename,n..n;strcpyroot-exname,nn;root-attribute=0x28;root-time=nowtime-tm_hour*2048+nowtime-tm_min*32+nowtime-tm_sec/2;root-date=nowtime-tm_year-80*512+nowtime-tm_mon+1*32+nowtime-tm_mday;root-first=5;root-length=2*sizeoffcb;root-free=1;fp=fopenmyfilename,nwn;fwritemyvhard,SIZE,1,fp;fclosefp;void my_cdchar*dirnamechar*dir;intfd;「\\;〃分解字符串为一组字符串为要分解的字符串,dir=strtokdirname dirname为分隔符字符串ifstrcmpdir,n.n==0return;else ifstrcmpdir,H..n==0ifcurdircurdir=my__closecurdir;return;}else ifstrcmpdir,Hrootn==0whilecurdircurdir=my_closecurdir;dir=strtokNULL,n\\n;}whiledirfd=my_opendir;iffd!=-1curdir=fd;elsereturn;dir=strtokNULL,H\\M;}}void my_mkdirchar*dirnamefcb*fcbptr;fat*fatl,*fat2;time_t now;struct tm*nowtime;char text[MAXTEXT];unsigned shortblkno;int rbn,fd,i;fatl=fat*myvhard+BLOCKSIZE;fat2=fat*myvhard+3*BLOCKSIZE;openfilelist[curdir].count=0;rbn=do_readcurdir,openfilelist[cur dir].length,text;fcbptr=fcb*text;〃在当前目录下找,是否有重名目录fori=0;irbn/sizeoffcb;i++{ifstrcmpfcbptr-filename,dirname==0strcmpfcbptr-exname,nn==0print*Error,the dirnameis alreadyexist!\nu;return;}fcbptr++;}fcbptr=fcb*text;十十fori=0;irbn/sizeoffcb;i{iffcbptr-free==0break;fcbptr++;行〃寻找空闲盘块blkno=ndblock;ifblkno==-1return;fatl+blkno-id=END;fat2+blkno-id=END;now=timeNULL;nowtime=localtimenow;strcpyfcbptr-filename,dirname;strcpyfcbptr-exname,nn;fcbptr-attribute=0x30;fcbptr-time=nowtime-tm_hour*2048+nowtime-tm_min*32+nowtime-tm_sec/2;fcbptr-date=nowtime-tm_year-80*512+nowtiine-tm_mon+1*32+nowtime-tm_mday;fcbptr-first=blkno;fcbptr-length=2*sizeoffcb;fcbptr-free=1;把当前目录的文件读写指针定位到文件末尾openfilelist[curdir].count=i*sizeoffcb;//〃从指针开始写一个大小的内容do_writecurdir,char*fcbptr,sizeoffcb,2;fcbptr fcb到当前目录文件末尾〃返回新建立的目录文件在用户打开文件数组的下标fd=my_opendirname;iffd==-1return;〃建立新目录的「目录fcbptr=fcb*mallocsizeoffcb;1,now=timeNULL;nowtime=localtimenow;strcpyfcbptr-filename,M.n;strcpyfcbptr-exname,MM;fcbptr-attribute=0x28;fcbptr-time=nowtime-tm_hour*2048+nowtime-tm_min*32+nowtime-tm_sec/2;fcbptr-date=nowtime-tm_year-80*512+nowtime-tm_mon+1*32+nowtime-tm_inday;fcbptr-first=blkno;fcbptr-length=2*sizeoffcb;fcbptr-free=1;do_writefd,char*fcbptr,sizeoffcb,2;now=timeNULL;nowtime=localtimenow;strcpyfcbptr-filename,n..n;strcpyfcbptr-exname,nn;fcbptr-attribute=0x28;fcbptr-time=nowtime-tm_hour*2048+nowtime-tm_min*32+nowtime-tm_sec/2;fcbptr-date=nowtime-tm_year-80*512+nowtime-tm_mon+1*32+nowtime-tm_iriday;fcbptr-first=blkno;fcbptr-length=2*sizeoffcb;fcbptr-free=1;do_writefd,char*fcbptr,sizeoffcb,2;freefcbptr;my_closefd;fcbptr=fcb*text;fcbptr-length=openfilelist[curdir].length;openfilelist[curdir].count=0;〃更新当前目录文件的内容do_writecurdir,char*fcbptr,sizeoffcb,2;openfilelist[curdir].fcbstate=1;}void my_rmdirchar*dirnamefcb*fcbptr,*fcbptr2;fat*fat2,*fatptr2;char text[MAXTEXT],text2[MAXTEXT];unsigned shortblkno;int rbn,rbn2,fd,i,j;fatl=fat«myvhard+BLOCKSIZE;fat2=fat*myvhard+3*BLOCKSIZE;ifstrcmpdirname,n.n==0||strcmpdirname,H..n==0printfEiror,cant removethis directory.\nu;return;openfilelist[curdir].count=0;rbn=do_readcurdir,openfilelist[curdir]Jength,text;fcbptr=fcb*text;〃查找要删除的目录fori=0;irbn/sizeoffcb;i++ifstrcmpfcbptr-filename,dirname==0strcmpfcbptr-exname,HH==0break;fcbptr++;}ifi==rbn/sizeoffcbprintfHError,the directoryis notexistin;return;〃目录在当前打开文件数组中的下标fd=my_opendimame;rbn2=do_readfd,〃读取要删除的目录的内容openfilelist[fd].length,text2;fcbptr2=fcb*text2;〃判断要删除目录是否为空forj=0;j rbn2/sizeoffcb;j++ifstrcmpfcbptr2-filename,strcmpfcbptr2-filename,strcmpfcbptr2-filename,nHmy_closefd;printfHError,the directoryis notempty.\nn;}〃修改要删除目录在return;fcbptr2++;blkno=openfilelist[fd].first;whileblkno!=END fat中所占用的目录项的属性|fatptrl=fatl+blkno;fatptr2=fat2+blkno;blkno=fatptrl-id;fatptrl-id=FREE;fatptr2-id=FREE;}my_closefd;strcpyfcbptr・filenamej;〃修改已删除目录在当前目录的fcb的属性fcbptr-free=0;〃更新当前目录文件的内容openfilelist[curdir].count=i*sizeoffcb;do_writecurdir,char*fcbptr,sizeoffcb,2;openfilelist[curdir].fcbstate=1;}void my_ls fcb*fcbptr;char text[MAXTEXT];int rbn,i;openfilelist[curdir].count=0;rbn=do_readcurdir,openfilelist[curdir].length,text;fcbptr=fcb*text;fori=0;irbn/sizeoffcb;i++iffcbptr-freeiffcbptr-attribute0x20printfn%s\\\t\tDIR\t\t%d/%d/%d\t%02d:%02d:%02d\n,\fcbptr-filename,fcbptr-date»9+1980,fcbptr-date»5OxOOOf,fcbptr-date OxOOlf,fcbptr-time»11,fcbptr-time»50x003f,fcbptr-timeOxOOlf*2;elseprintfn%s.%s\t\t%dB\t\t%d/%d/%d\t%02d:%02d:%02d\t\nn,fcbptr-filename fcbptr-exname,intfcbptr-length,fcbptr-date»9+1980,fcbptr-date9»5OxOOOf,fcbptr-dateOxlf,fcbptr-time»11,fcbptr-time»50x3f,fcbptr-time Oxlf*2;}fcbptr++;}}void my_createchar*filenamefcb*fcbptr;fat*fat2;char*fname,*exname,text[MAXTEXT];unsigned shortblkno;int rbn,i;time_t now;struct tm*nowtime;fatl=fat*myvhard+BLOCKSIZE;fat2=fat*myvhard+BLOCKSIZE;fname=strtokfilename,n.n;exname=strtokNULL,n.n;ifstrcmpfname,nn==0printff*Error,creating filemust havea rightname.\nH;return;}if!exnameprintfnError,creating filemust havea extern nameAnu;return;}openfilelist[curdir].count=0;rbn=do_readcurdir,openfilelist[curdir].length,text;fcbptr=fcb*text;fori=0;irbn/sizeoffcb;i++{ifstrcmpfcbptr-filename,fname==0strcmpfcbptr-exname,exname==0printff*Error,the filenameis alreadyexist!\nn;
③列出文件系统提供的各项功能及命令调用格式;
④显示命令行提示符,等待用户输入命令;
⑤将用户输入的命令保存到一个中;buf
⑥对中的内容进行命令解析,并调用相应的函数执行用户键入的命令;buf
⑦如果命令不是则命令执行完毕后转
④my.exitsys,进入文件系统函数
2.startsys对应命令无1命令调用格式无2函数设计格式:3void startsys功能由函数调用,进入并初始化我们所建立的文件系统,以供用户使用4main输入:无5输出无6函数需完成的工作7
①申请虚拟磁盘空间;
②使用语言的库函数打开文件若文件存在,则转
③;若文件不存在,则创c fopenmyfsys建之,转
⑤③使用语言的库函数读入文件内容到用户空间中的一个缓冲区中,并判断其c freadmyfsys开始的个字节内容是否为文件系统魔数,如果是,则转
④;否则转
⑤;8“10101010”
④将上述缓冲区中的内容复制到内存中的虚拟磁盘空间中;转
⑦⑤在屏幕上显示文件系统不存在,现在开始创建文件系统”信息,并调用“myfsys my_format对
①中申请到的虚拟磁盘空间进行格式化操作转
⑥;
⑥将虚拟磁盘中的内容保存到文件中;转
⑦myfsys
⑦使用语言的库函数关闭文件;c fclosemyfsys
⑧初始化用户打开文件表,将表项分配给根目录文件使用,并填写根目录文件的相关信息,0由于根目录没有上级目录,所以表项中的和分别置为根目录所在起始块号和dirn diroff50;并将ptrcurdir指针指向该用户打开文件表项
⑨将当前目录设置为根目录磁盘格式化函数
3.my_format对应命令1my_format命令调用格式2my_format函数设计格式3void my_format功能对虚拟磁盘进行格式化,布局虚拟磁盘,建立根目录文件或根目录区4输入无5输出无6函数需完成的工作7
①将虚拟磁盘第一个块作为引导块,开始的8个字节是文件系统的魔数,记为“10101010”;在之后写入文件系统的描述信息,如表大小及位置、根目录大小及位置、盘块大小、盘块FAT数量、数据区开始位置等信息;2在引导块后建立两张完全一样的FAT表,用于记录文件所占据的磁盘块及管理虚拟磁盘块的分配,每个占据两个磁盘块;对于每个中,前面个块设置为已分配,后面FAT FAT5995个块设置为空闲;3在第二张FAT后创建根目录文件root,将数据区的第1块即虚拟磁盘的第6块分配给根目录文件,在该磁盘上创建两个特殊的目录项“.”和其内容除了文件名不同之return;}fcbptr++;}fcbptr=fcb*text;fori=0;irbn/sizeoffcb;i++iffcbptr-free==0break;fcbptr++;}blkno=flndblock;ifblkno==-1return;fatl+blkno-id=END;fat2+blkno-id=END;now=timeNULL;nowtime=localtimenow;strcpyfcbptr-filename,fname;strcpyfcbptr-exname,exname;fcbptr-attribute=0x00;fcbptr-time=nowtime-tm_hour*2048+nowtime-tm_min*32+nowtime-tm_sec/2;fcbptr-date=nowtime-tm_year-80*512+nowtime-tm_mon+1*32+nowtime-tm_mday;fcbptr-first=blkno;fcbptr-length=0;fcbptr-free=1;openfilelist[curdir].count=i*sizeoffcb;do_writecurdir,char*fcbptr,sizeoffcb,2;fcbptr=fcb*text;fcbptr-length=openfilelist[curdir].length;openfilelist[curdir].count=0;do_writecurdir,char*fcbptr,sizeoffcb,2;openfilelist[curdir].fcbstate=1;void my_rmchar*filenamefcb*fcbptr;fat*fat2,*fatptrl,*fatptr2;char*fname,*exname,text[MAXTEXT];unsigned shortblkno;int rbn,i;fatl=fat*myvhard+BLOCKSIZE;fat2=fat*myvhard+3*BLOCKSIZE;fname=strtokfilename,n.n;exname=strtokNULL,H.n;ifstrcmpfname,nn==0printf11Error,removing filemust havea rightname.\nH;return;}if!exnameprintfnError,removing filemust havea extern name.\nM;return;}openfilelist[curdir].count=0;rbn=do_readcurdir,openfilelist[curdir].length,text;fcbptr=fcb*text;fori=0;irbn/sizeoffcb;i++ifstrcmpfcbptr-filename,fname==0strcmpfcbptr-exname,exname==0break;fcbptr++;}ifi==rbn/sizeoffcbprintf11Error,the file is notexist An;return;}blkno=fcbptr-first;whileblkno!=END fatptrl=fatl+blkno;fatptr2=fat2+blkno;blkno=fatptrl-id;fatptrl-id=FREE;fatptr2-id=FREE;}strcpyfcbptr-filename,,,H;fcbptr-free=0;openfilelist[curdir].count=i*sizeoffcb;do_writecurdir,char*fcbptr,sizeoffcb,2;openfilelist[curdir].fcbstate=1;int my_openchar^filename fcb*fcbptr;char*fname,exname
[3],*str,text[MAXTEXT];int rbn,fd,i;fname=strtokfilename,n.n;str=strtokNULL,n.n;ifstrstrcpyexname,str;elsestrcpyexname,nn;〃在用户打开文件数组查找看当前文件是否已经打开fori=0;iMAXOPENFILE;i++{ifstrcmpopenfilelist[i].filename,fname==0strcmpopenfilelist[i].exname,exname==0i!=curdirprintfHError,thefileis alreadyopen.\nu;return-1;openfilelist[curdir].count=0;rbn=do_readcurdir,openfllelist[curdir].length,text;fcbptr=fcb*text;〃在当前目录下找要打开的文件是否存在fori=0;irbn/sizeoffcb;i++ifstrcmpfcbptr-filename,fname==0strcmpfcbptr-exname,exname==0break;fcbptr++;ifi==rbn/sizeoffcbprintfMError,thefileis notexistin;return-1;自;//寻找空闲文件表项fd=ndopenfileiffd==-1return-1;strcpyopenfilelist[fd].filename,fcbptr-filename;strcpyopenfilelist[fd].exname,fcbptr-exname;openfilelist[fd].attribute=fcbptr-attribute;openfilelist[fd].time=fcbptr-time;openfilelist[fd].date=fcbptr-date;openfilelist[fd].first=fcbptr-first;openfilelist[fd].length=fcbptr-length;openfilelist[fd].free=fcbptr-free;openfilelist[fd].dirno=openfilelist[curdir].first;openfilelist[fd].diroff=i;strcpyopenfilelist[fd].dir,openfilelist[curdir].dir;strcatopenfilelist[fd].dir,filename;iffcbptr-attribute0x20strcatopenfilelist[fd].dir,n\\n;openHIelist[fd].father=curdir;openfilelist[fd].count=0;openfilelist[fd].fcbstate=0;openfilelist[fd].topenfile=1;return fd;int my_closeint fdfcb*fcbptr;int father;iffd0||fd=MAXOPENFILE printf11Error,the Hieis notexist.\nn;return-1;}ifopenfilelist[fd].fcbstatefcbptr=fcb*mallocsizeoffcb;strcpyfcbptr-filename,openfilelist[fd].filename;strcpyfcbptr-exname,openfilelist[fd].exname;fcbptr-attribute=openfilelist[fd].attribute;fcbptr-time=openfilelist[fd].time;fcbptr-date=openfilelist[fd].date;fcbptr-first=openfilelist[fd].first;fcbptr-length=openfilelist[fd].length;fcbptr-free=openfilelist[fd].free;father=openfilelist[fd].father;openfilelist[father].count=openfilelist[fd].diroff*sizeoffcb;do_writefather,char*fcbptr,sizeoffcb,2;freefcbptr;openfilelist[fd].fcbstate=0;strcpyopenfilelist[fd].filename,nn;strcpyopenfilelist[fd].exname,nH;openfilelist[fd].topenfile=0;return father;int my_writeint fdfat*fat2,*fatptrl,*fatptr2;int wstyle,len,11,tmp;char text[MAXTEXT];unsigned shortblkno;fatl=fat*myvhard+BLOCKSIZE;fat2=fat*myvhard+3*BLOCKSIZE;iffd0||fd=MAXOPENFILE printfMThefileisnotexist!\nn;return-1;whilelprintfHPlease enterthe numberof writestyle:\nLent write\t
2.cover write\t
3.addwrite\nn;scanfH%dH,wstyle;ifwstyle0wstyle4break;printfnInput Error!n;}getchar;switchwstyle〃截断写把原文件所占的虚拟磁盘空间重置为case1:1blkno=openfilelist[fd].first;fatptrl=fatl+blkno;fatptr2=fat2+blkno;blkno=fatptrl-id;fatptrl-id=END;fatptr2-id=END;whileblkno!=END fatptrl=fatl+blkno;fatptrl=fat2+blkno;blkno=fatptrl-id;fatptrl-id=FREE;fatptr2-id=FREE;openfilelist[fd].count=0;openfilelist[fd].length=0;break;openfilelist[fd].count=0;break;openfilelist[fd].count=openfilelist[fd].length;break;default:break;}II=0;printfnplease inputwrite dataendwith Ctrl+Z:\nn;whilegetstext{len=strlentext;text[len++]=\n;text[len]=\0;tmp=do_writefd,text,len,wstyle;iftmp!=-111+=tmp;iftmplen|printfHWirte Error!n;break;〃实际写的字节数return H;}int do_writeint fd,char*text,int len,char wstylefat*fat2,*fatptrl,*fatptr2;unsigned char*buf,*blkptr;unsigned shortblkno,blkoff;int i11;9fatl=fat*myvhard+BLOCKSIZE;fat2=fat*myvhard+3*BLOCKSIZE;buf=unsigned char*mallocBLOCKSIZE;ifbuf==NULL{printfnmalloc failed!\nH;return-1;}blkno=openfilelist[fd].first;blkoff=openfilelist[fd].count;fatptrl=fatl+blkno;fatptr2=fat2+blkno;whileblkoff=BLOCKSIZEblkno=fatptrl-id;|ifblkno==ENDblkno=findblock;ifblkno==-1freebuf;return-1;}fatptrl-id=blkno;fatptr2-id=blkno;fatptrl=fatl+blkno;fatptr2=fat2+blkno;fatptrl-id=END;fatptr2-id=END;}else|fatptrl=fatl+blkno;fatptr2=fat2+blkno;〃让定位到文件最后一个磁盘块的读写位置blkoff=blkoff-BLOCKSIZE;blkoff11=0;〃实际写的字节数是用户输入的字节数whilelllen//lenblkptr=unsigned char*myvhard+blkno*BLOCKSIZE;fori=0;i BLOCKSIZE;i++buf[i]=blkptr[i];for;blkoff BLOCKSIZE;blkoff++buf[blkoff]=text[11++];openfllelist[fd].count++;ifll==lenbreak;fori=0;i BLOCKSIZE;i++blkptr[i]=buf[i];〃如果一个磁盘块写不下,则再分配一个磁盘块iflllenblkno=fatptrl-id;ifblkno==ENDblkno=findblock;ifblkno==-1break;fatptrl-id=blkno;fatptr2-id=blkno;fatptrl=fatl+blkno;fatptrl=fat2+blkno;fatptrl-id=END;fatptr2-id=END;elsefatptrl=fatl+blkno;fatptr2=fat2+blkno;blkoff=0;}ifopenfilelist[fd].countopenfilelist[fd].lengthopenfilelist[fdj.length=openfilelist[fd].count;openfilelist[fd].fcbstate=1;freebuf;return11;int my_readint fd,int lenchartext[MAXTEXT];int11;iffd0||fd=MAXOPENFILEprintfHThe Fileisnotexist!\nn;return-1;}openfilelist[fd].count=0;是实际读出的字节数11=do_readfd,len,text;//llifll!=-1printfH%s,\text;elseprintfHRead Error!\nM;return11;int do_readint fd,int len,char*text fat*fatl,^fatptr;unsigned char*buf,*blkptr;unsigned shortblkno,blkoff;int i,11;fatl=fat*myvhard+BLOCKSIZE;buf=unsigned char*mallocBLOCKSIZE;ifbuf==NULL printfnmallocfailed!\nH;return-1;blkno=openfilelist[fd].first;blkoff=openfilelist[fd].count;ifblkoff=openfilelist[fd].length putsHReadout ofrange!1*;freebuf;return-1;}fatptr=fatl+blkno;为最后一块盘块剩余的容量whileblkoff=BLOCKSIZE//blkoffblkno=fatptr-id;blkoff=blkoff-BLOCKSIZE;fatptr=fatl+blkno;}11=0;whilelllen blkptr=unsigned char*myvhard+blkno*BLOCKSIZE;〃将最后一块盘块的内容读取到中fori=0;i BLOCKSIZE;i++buf buf[i]=blkptr[i];for;blkoffBLOCKSIZE;blkoff++text[ll++]=buf[blkoff];openfilelist[fd].count++;ifll==len||openfilelist[fd].count==openfilelist[fd].length break;iflllenopenfilelist[fd].count!=openfilelist[fd].lengthblkno=fatptr-id;ifblkno==ENDbreak;blkoff=0;fatptr=fatl+blkno;}}text[U]=\0;freebuf;return11;void my_exitsysFILE*fp;whilecurdircurdir=my_closecurdir;fp=fopenmyfilename,nwn;fwritemyvhard,SIZE,1,fp;fclosefp;freemyvhard;unsigned shortfindblockunsigned shorti;fat*fatl,*fatptr;fatl=fat*myvhard+BLOCKSIZE;fori=7;i SIZE/BLOCKSIZE;i++|fatptr=fatl+i;iffatptr-id==FREE return i;printfnError,Can*tfindfree block!\nn;return-1;int HndopenHIeinti;fori=0;i MAXTEXT;i++ifopenfilelist[i].topenfile==0returni;外,其他字段完全相同更改当前目录函数
4.my_cd对应命令1my_cd命令调用格式2my_cd dirname函数设计格式3void my_cdchar*dirname功能改变当前目录到指定的名为的目录4dirname输入5dirname新的当前目录的目录名;输出无6函数需完成的工作71调用my_open打开指定目录名的父目录文件,并调用do」ead读入该父目录文件内容到内存中;2在父目录文件中检查新的当前目录名是否存在,如果存在则转
③,否则返回,并显示出错信息;
③调用关闭
①中打开的父目录文件;my_close
④调用关闭原当前目录文件;my_close5如果新的当前目录文件没有打开,则打开该目录文件;并将ptrcurdir指向该打开文件表项;
⑥设置当前目录为该目录创建子目录函数
5.my_mkdir对应命令1my_mkdir命令调用格式2my_mkdir dirname函数设计格式3void my_mkdirchar*dirname功能在当前目录下创建名为的子目录4dirname输入5dirname新建目录的目录名输出无6函数需完成的工作7
①调用」读入当前目录文件内容到内存,检查当前目录下新建目录文件是否重名,若do ead重名则返回,并显示错误信息;2为新建子目录文件分配一个空闲打开文件表项,如果没有空闲表项则返回・1,并显示错误信息;
③检查是否有空闲的盘块,如有则为新建目录文件分配一个盘块,否则释放
①中分配的FAT打开文件表项,返回,并显示错误信息;
④在当前目录中为新建目录文件寻找一个空闲的目录项或为其追加一个新的目录项;需修改当前目录文件的长度信息,并将当前目录文件的用户打开文件表项中的fcbstate置为1;5准备好新建目录文件的FCB的内容,文件的属性为目录文件,以覆盖写方式调用do_write将其填写到对应的空目录项中;6在新建目录文件所分配到的磁盘块中建立两个特殊的目录项和目录项,方法是首先在用户空间中准备好内容,然后以截断写或者覆盖写方式调用将其写到
③中分配到的磁do_write盘块中;
⑦返回删除子目录函数
6.rmdir对应命令1my_rmdirprintf**Error,open toomany files!\nH;return-1;int maincharcmd
[15]
[10]={cd,mkdir\rmdir\Ts create,rm,open,close,write1;nread,\nexitn};char s
[30],*sp;int cmdn,flag=1,i;startsys;•/*/ffWWW WWWSystem,,木本不不不不不小小不不不不/米不不不不不不卜ilp)[0******************************•printfC命令名\t\t命令参数\t\t命令说明\n\n”);printf(ncd\t\t目录名(路径名)\t\t切换当前目录到指定目录\n);print(f Hmkdir\t\t目录名\t\t\t在当前目录创建新目录\n);printf(nrmdir\t\t目录名\t\t\t在当前目录删除指定目录\n”);printf(nls\t\t无\t\t\t显示当前目录下的目录和文件\n);printf(ncreate\t\t文件名\t\t\t在当前目录下创建指定文件\n);printf(urm\t\t文件名\t\t\t在当前目录下删除指定文件\n);printf(Hopen\t\t文件名\t\t\t在当前目录下打开指定文件\n”);printfnwrite\t\t无\t\t\t在打开文件状态下,写该文件\n”);读printfnread\t\t无\t\t\t在打开文件状态下,取该文件\n);读printfuclose\t\t无\t\t\t在打开文件状态下,取该文件\n);printfHexit\t\t无\t\t\t退出系统\n\n”;,f*2^*2**2**2**2^*2**2**2**2*%■A****g*¥rj*rj*r1w rj rjw rjw rj*rj»rj rjw rjw rjw rj*rjw rjw rj rjw r|*rj*rj rjwrj*rjwr1*rjw rjwrj*rj*rjwrj rjw rjwrj*rj rjwrjrj rjwrj*rj*ej*rjwrjrjwrjwrjrjwrj»rj*rj*ejw rjrjrjwrj*rj\1nn;whileflagprintfn%sH,openfilelist[curdir].dir;getss;cmdn=-1;ifstrcmps,nnsp=strtoks,M M;fori=0;i15;i++ifstrcmpsp,cmd[i]==0cmdn=i;break;//printfn%d\nn,cmdn;switchcmdncase0:sp=strtokNULL,n n;ifspopenfilelist[curdir].attribute0x20my_cdsp;elseprintfHPlease inputthe rightcommand.\nn;break;sp=strtokNULL,n H;ifspopenfilelist[curdir].attribute0x20my_mkdirsp;elseprintfHPlease inputthe rightcommand An;break;sp=strtokNULL,nn;ifspopenfilelist[curdir].attribute0x20my_rmdirsp;elseprintfHPlease inputthe rightcommandin;break;ifopenfilelist[curdir].attribute0x20my_ls;elseprintfHPlease inputthe rightcommandin;break;sp=strtokNULL,M H;ifspopenfilelist[curdir].attribute0x20my_createsp;elseprintfHPlease inputthe rightcommand An;break;sp=strtokNULL,nn;ifspopenfilelist[curdir].attribute0x20my_rmsp;elseprintfHPlease inputthe rightcommand.\nu;break;sp=strtokNULL,M H;ifspopenfilelist[curdir].attribute0x20「〃查找中「首次出现的位置ifstrchrspj spcurdir=my_opensp;elseprintfMthe openfileshould haveexname.\nu;elseprintfnPlease inputthe rightcommand An;break;if!openfilelist[curdir].attribute0x20curdir=my_closecurdir;elseprintfHNo filesopened.\nn;break;if!openfilelist[curdir].attribute0x20my_writecurdir;elseprintfHNo filesopened.\nM;break;if!openfilelist[curdir].attribute0x20my_readcurdir,openfilelist[curdir].length;elseprintfHNo filesopened.\nM;break;ifopenfilelist[curdir].attribute0x20my_exitsys;flag=0;elseprintfHPlease inputthe rightcommandin;break;default:printfHPlease inputthe rightcommand.\nn;break;return0;
四、总结(包括设计过程中遇到的问题及解决办法、程序的不足分析及改进建议、课程设计的收获等)在我们小组实验过程中,刚开始对当前目录和当前目录的父目录这些问题,理解的不是特别清楚还有就是在表的构造过程中,每个元素所对应的含义没有理得十分清楚FAT fa tFa t表中的元素与数据块的对应关系,在我们整个个实验过程中是非常重要的程序中的不足是在函数中,这个形参没有在函数中实现全部的功能写的功my_wri te wstyle能只实现了覆盖写毫无疑问,通过这次实验,我们分组的各个小组的成员都比以前更加熟悉,关系也更加友好最重要的是,在一块讨论问题的时候,彼此针对相关问题的争论使问题更加快的变明了命令调用格式2my_rmdir dirname函数设计格式1void my_rmdirchar*dirname功能在当前目录下删除名为的子目录2dirname输入3dirname欲删除目录的目录名输出:无4函数需完成的工作5
①调用」读入当前目录文件内容到内存,检查当前目录下欲删除目录文件是否存在,do ead若不存在则返回,并显示错误信息;
②检查欲删除目录文件是否为空除了和外没有其他子目录和文件,可根据其目录项中记录的文件长度来判断,若不为空则返回,并显示错误信息;
③检查该目录文件是否已经打开,若已打开则调用关闭掉;my_close4回收该目录文件所占据的磁盘块,修改FAT;
⑤从当前目录文件中清空该目录文件的目录项,且free字段置为0以覆盖写方式调用do_write来实现;
⑥修改当前目录文件的用户打开表项中的长度信息,并将表项中的fcbstate置为1;
⑦返回显示目录函数」
7.my s对应命令1my_ls命令调用格式2myjs函数设计格式3void myjsvoid功能显示当前目录的内容子目录和文件信息4输入无5输出无6函数需完成的工作7
①调用」读出当前目录文件内容到内存;do ead
②将读出的目录文件的信息按照一定的格式显示到屏幕上;
③返回创建文件函数
8.my_create对应命令1my_create命令调用格式2my_create filename函数设计格式3int my_create char*filename功能创建名为的新文件4filename输入5filename新建文件的文件名,可能包含路径输出若创建成功,返回该文件的文件描述符文件打开表中的数组下标;否则返回6函数需完成的工作7
①为新文件分配一个空闲打开文件表项,如果没有空闲表项则返回并显示错误信息;
②若新文件的父目录文件还没有打开,则调用打开;若打开失败,则释放
①中为新建文件my_open分配的空闲文件打开表项,返回并显示错误信息;
③调用」读出该父目录文件内容到内存,检查该目录下新文件是否重名,若重名则释do ead放
①中分配的打开文件表项,并调用关闭
②中打开的目录文件;然后返回“,并显my_close示错误信息;
④检查是否有空闲的盘块,如有则为新文件分配一个盘块,否则释放
①中分配的打开文FAT件表项,并调用关闭
②中打开的目录文件;返回并显示错误信息;my_close
⑤在父目录中为新文件寻找一个空闲的目录项或为其追加一个新的目录项;需修改该目录文件的长度信息,并将该目录文件的用户打开文件表项中的fcbstate置为1;
⑥准备好新文件的的内容,文件的属性为数据文件,长度为以覆盖写方式调用FCB0,do_write将其填写到
⑤中分配到的空目录项中;
⑦为新文件填写
①中分配到的空闲打开文件表项,fcbstate字段值为0,读写指针值为0;
⑧调用关闭
②中打开的父目录文件;my_dose
⑨将新文件的打开文件表项序号作为其文件描述符返回删除文件函数
9.my_rm对应命令1my_rm命令调用格式2my_rm filename函数设计格式3void my_rmchar filename功能删除名为的文件4filename输入:5filename欲删除文件的文件名,可能还包含路径输出无6函数需完成的工作7
①若欲删除文件的父目录文件还没有打开,则调用打开;若打开失败,则返回,并my_open显示错误信息;
②调用」读出该父目录文件内容到内存,检查该目录下欲删除文件是否存在,若不存do ead在则返回,并显示错误信息;
③检查该文件是否已经打开,若已打开则关闭掉;
④回收该文件所占据的磁盘块,修改FAT;
⑤从文件的父目录文件中清空该文件的目录项,且free字段置为0以覆盖写方式调用do_write来实现;;
⑥修改该父目录文件的用户打开文件表项中的长度信息,并将该表项中的fcbstate置为1;
⑦返回打开文件函数
10.my_open对应命令:1my_open命令调用格式2my_open filename3函数设计格式intmy_openchar*filename功能打开当前目录下名为行的文件4lename输入5filename欲打开文件的文件名输出若打开成功,返回该文件的描述符在用户打开文件表中表项序号;否则返回6函数需完成的工作7
①检查该文件是否已经打开,若已打开则返回并显示错误信息;
②调用读出父目录文件的内容到内存,检查该目录下欲打开文件是否存在,若不存do_read在则返回并显示错误信息;
③检查用户打开文件表中是否有空表项,若有则为欲打开文件分配一个空表项,若没有则返回并显示错误信息;
④为该文件填写空白用户打开文件表表项内容,读写指针置为0;
⑤将该文件所分配到的空白用户打开文件表表项序号数组下标作为文件描述符返回fd
11.关闭文件函数my_dose对应命令1my_close命令调用格式2my_close fd函数设计格式3void my_closeint fd功能关闭前面由打开的文件描述符为的文件4my_open fd输入5fd文件描述符输出无6函数需完成的工作71检查fd的有效性fd不能超出用户打开文件表所在数组的最大下标,如果无效则返回-1;2检查用户打开文件表表项中的fcbstate字段的值,如果为1则需要将该文件的FCB的内容保存到虚拟磁盘上该文件的目录项中,方法是打开该文件的父目录文件,以覆盖写方式调用将欲关闭文件的写入父目录文件的相应盘块中;do_write FCB
③回收该文件占据的用户打开文件表表项进行清空操作,并将topenfile字段置为0;
④返回写文件函数
12.my_write对应命令1my_write命令调用格式2my_write fd函数设计格式:3int my_writeint fd功能将用户通过键盘输入的内容写到所指定的文件中磁盘文件的读写操作都必须以4fd完整的数据块为单位进行,在写操作时,先将数据写在缓冲区中,缓冲区的大小与磁盘块的大小相同,然后再将缓冲区中的数据一次性写到磁盘块中;读出时先将一个磁盘块中的内容读到缓冲区中,然后再传送到用户区本实例为了简便起见,没有设置缓冲区管理,只是在读写文件时由用户使用申请一块空间作为缓冲区,读写操作结束后使用释放掉malloc free写操作常有三种方式截断写、覆盖写和追加写截断写是放弃原来文件的内容,重新写文件;覆盖写是修改文件在当前读写指针所指的位置开始的部分内容;追加写是在原文件的最后添加新的内容在本实例中,输入写文件命令后,系统会出现提示让用户选择其中的一种写方式,并将随后键盘输入的内容按照所选的方式写到文件中,键盘输入内容通过键或其他设CTR+Z定的键结束输入5fdopen函数的返回值,文件的描述符;输出实际写入的字节数6函数需完成的工作7
①检查的有效性不能超出用户打开文件表所在数组的最大下标,如果无效则返回并fd fd-1,显示出错信息;
②提示并等待用户输入写方式L截断写;2覆盖写;3追加写
③如果用户要求的写方式是截断写,则释放文件除第一块外的其他磁盘空间内容查找并修改表,将内存用户打开文件表项中文件长度修改为将读写指针置为并转
④;如果用户FAT0,0要求的写方式是追加写,则修改文件的当前读写指针位置到文件的末尾,并转
④;如果写方式是覆盖写,则直接转
④;
④提示用户整个输入内容通过键或其他设定的键结束;用户可分多次输入写入内CTR+Z容,每次用回车结束;
⑤等待用户从键盘输入文件内容,并将用户的本次输入内容保存到一临时变量口中,要求text每次输入以回车结束,全部结束用键或其他设定的键;CTR+Z6调用do_write函数将通过键盘键入的内容写到文件中7如果do_write函数的返回值为非负值,则将实际写入字节数增加do_write函数返回值,否则显示出错信息,并转
⑨;
⑧如果口中最后一个字符不是结束字符则转
⑦继续进行写操作;否则转
⑨;
⑨如text CTR+Z,果当前读写指针位置大于用户打开文件表项中的文件长度,则修改打开文件表项中的文件长度信息,并将fcbstate置1;⑩返回实际写入的字节数实际写文件函数
13.do_write对应命令无1命令调用格式无2函数设计格式3int my_writeint fd,char*text,int lenchar wstyle功能被写文件函数调用,用来将键盘输入的内容写到相应的文件中去4my_write输入:5fdopen函数的返回值,文件的描述符;text指向要写入的内容的指针;len本次要求写入字节数wstyle写方式输出实际写入的字节数6函数需完成的工作7
①用申请的内存空间作为读写磁盘的缓冲区申请失败则返回并显示出错信mallocO1024B buf,息;
②将读写指针转化为逻辑块块号和块内偏移并利用打开文件表表项中的首块号及表的off,FAT相关内容将逻辑块块号转换成对应的磁盘块块号;如果找不到对应的磁盘块,则需要检blkn索为该逻辑块分配一新的磁盘块,并将对应的磁盘块块号登记到中,若分配FAT blknoFAT失败,则返回」,并显示出错信息;
③如果是覆盖写,或者如果当前读写指针所对应的块内偏移不等于则将块号为的虚off0,blkno拟磁盘块全部1024B的内容读到缓冲区buf中;否则便用ASCII码0清空buf;
④将中未写入的内容暂存到缓冲区的第字节开始的位置,直到缓冲区满,或者接text buffff收到结束字符为止;将本次写入字节数记录到中;CTR+Z tmplen
⑤将中的内容写入到块号为的虚拟磁盘块中;buf1024B blkno
⑥将当前读写指针修改为原来的值加上tmplen;并将本次实际写入的字节数增加tmplen;7如果tmplen小于len,则转
②继续写入;否则转
⑧;8返回本次实际写入的字节数读文件函数
14.my_read对应命令1my_read命令调用格式2my_rcad fdIcn函数设计格式3int myread intfd,int len功能读出指定文件中从读写指针开始的长度为的内容到用户空间中4len输入5fdopen函数的返回值,文件的描述符;要从文件中读出的字节数len:输出实际读出的字节数6函数需完成的工作7
①定义一个字符型数组用来接收用户从文件中读出的文件内容;text[len],
②检查的有效性不能超出用户打开文件表所在数组的最大下标,如果无效则返回fd fd并显示出错信息;-1,
③调用」将指定文件中的字节内容读出到口中;do eadlen text
④如果」的返回值为负,则显示出错信息;否则将口中的内容显示到屏幕上;
⑤do eadtext返回实际读文件函数
15.do_read对应命令无1命令调用格式无2函数设计格式3int do_readintfd,intlen,char*text功能被」调用,读出指定文件中从读写指针开始的长度为的内容到用户空间4my eadlen的中text输入:5fdopen函数的返回值,文件的描述符;要求从文件中读出的字节数len:text指向存放读出数据的用户区地址输出实际读出的字节数6函数需完成的工作7
①使用申请空间作为缓冲区申请失败则返回“,并显示出错信息;
②将读malloc1024B buf,写指针转化为逻辑块块号及块内偏移量利用打开文件表表项中的首块号查找表,找到off,FAT该逻辑块所在的磁盘块块号;将该磁盘块块号转化为虚拟磁盘上的内存位置;3将该内存位置开始的1024B一个磁盘块内容读入buf中;4比较buf中从偏移量ff开始的剩余字节数是否大于等于应读写的字节数len,如果是,则将从开始的中的长度的内容读入到口中;否则,将从开始的中的剩余内off buflen textoff buf容读入到口中;text5将读写指针增加
④中已读字节数,将应读写的字节数len减去
④中已读字节数,若len大于0,则转
②;否则转
⑥;6使用free释放
①中申请的buf
⑦返回实际读出的字节数退出文件系统函数
16.my_exitsys对应命令1my_exitsys命令调用格式2my_exitsys函数设计格式1void my_exitsys功能退出文件系统2输入无3输出无4函数需完成的工作5
①使用库函数打开磁盘上的文件;C fopenmyfsys
②将虚拟磁盘空间中的所有内容保存到磁盘上的文件中;myfsys
③使用语言的库函数关闭文件;c fclosemyfsys
④撤销用户打开文件表,释放其内存空间
⑤释放虚拟磁盘空间流程图
三、程序实现代码:#include stdio.h#include stdlib.h#include string.h#include time.h。