杭州电子科技大学操作系统课程设计课程设计题目:简单文件系统的实现姓名:徐凯辉班级:12052315学号:12224679学院:计算机学院专业:计算机科学与技术负责老师:贾刚勇报告完成日期:2014.12.30简单文件系统的实现一,课程设计的目的1.通过具体的文件爱你存储空间的管理、文件的物理结构、目录结构和文件操作的实现,加深对文件系统内部数据结、功能及实现过程的理解二,设计要求1.在内存中开辟一个虚拟磁盘空间作为文件存储分区,在其上实现一个简单的基于多级目录的但用户单任务系统的文件系统。在退出文件系统的使用时,应将虚拟文件系统一个Windows文件的方式保存到磁盘中,以便下次再将它恢复到内存的虚拟磁盘空间中2.文件存储空间的分配可采用显示链接分配或其它方法3.空闲磁盘空间的管理可选择位示图或其它方法4.文件目录结构采用多级目录结构5.需要提供一以下操作命令i.Formatii.Mkdiriii.Rmdiriv.Lsv.Cdvi.Createvii.Openviii.Closeix.Writex.Readxi.Rmxii.Exit三,程序设计思想以及总流程图1.程序设计思想i.首先,在文件系统启动时,申请一块较大的内存,用来当作文件系统的磁盘空间ii.然后,对其进行格式化,虚拟磁盘的空间布局是仿照FAT16文件系统,结构如下:1块2块2块995块引导块FAT1FAT2数据区格式化时,主要包括引导块,FAT1,FAT2,的一些初始化工作例如设置文件魔数,文件系统的信息,FAT1,FAT2的信息等等iii.根据用户输入的命令,调用对应的函数.2.程序流程图程序启动文件系统存在文件系统不存在等待用户输入命令。。。四,系统关键数据结构(1)文件控制块FCB用于记录文件的描述和控制信息,每个文件设置一个FCB,它也是文件的目录项的内容。typedefstructFCB//仿照FAT16设置的{charfilename[8];//文件名charexname[3];//文件扩展名unsignedcharattribute;//文件属性字段:为简单起见,我们只为文件设置了两种属性://值为0时表示目录文件,值为1时表示数据文件unsignedshorttime;//文件创建时间unsignedshortdata;//文件创建日期unsignedshortfirst;//文件起始盘块号unsignedlonglength;//文件长度(字节数)charfree;//表示目录项是否为空,若值为0,表示空,值为1,表示已分配}fcb;(2)文件分配表FAT加载文件系统创建新的文件系统并格式化lsMkdirCreateExittypedefstructFAT{unsignedshortid;}fat;(3)用户打开文件表USEROPEN当打开一个文件时,必须将文件的目录项中的所有内容全部复制到内存中,同时还要记录有关文件操作的动态信息,如读写指针的值等。在本实例中实现的是一个用于单用户单任务系统的文件系统,为简单起见,我们把用户文件描述符表和内存FCB表合在一起,称为用户打开文件表,表项数目为10,即一个用户最多可同时打开10个文件。然后用一个数组来描述,则数组下标即某个打开文件的描述符。另外,我们在用户打开文件表中还设置了一个字段“chardir[80]”,用来记录每个打开文件所在的目录名,以方便用户打开不同目录下具有相同文件名的不同文件。typedefstructUSEROPEN{charfilename[8];//文件名charexname[3];//文件扩展名unsignedcharattribute;//文件属性:值为0时表示目录文件,值为1时表示数据文件unsignedshorttime;//文件创建时间unsignedshortdata;//文件创建日期unsignedshortfirst;//文件起始盘块号unsignedlonglength;//文件长度(对数据文件是字节数,对目录文件可以是目录项个数)charfree;//表示目录项是否为空,若值为0,表示空,值为1,表示已分配//前面内容是文件的FCB中的内容。//下面设置的dirno和diroff记录了相应打开文件的目录项在父目录文件中的位置,//这样如果该文件的fcb被修改了,则要写回父目录文件时比较方便intdirno;//相应打开文件的目录项在父目录文件中的盘块号intdiroff;//相应打开文件的目录项在父目录文件的dirno盘块中的目录项序号chardir[MAXOPENFILE][80];//相应打开文件所在的目录名,这样方便快速检查出//指定文件是否已经打开intcount;//读写指针在文件中的位置charfcbstate;//是否修改了文件的FCB的内容,如果修改了置为1,否则为0chartopenfile;//表示该用户打开表项是否为空,若值为0,表示为空,否则表示已//被某打开文件占据}useropen;(4)引导块BLOCK0在引导块中主要存放逻辑磁盘的相关描述信息,比如磁盘块大小、磁盘块数量、文件分配表、根目录区、数据区在磁盘上的起始位置等。如果是引导盘,还要存放操作系统的引导信息。本实例是在内存的虚拟磁盘中创建一个文件系统,因此所包含的内容比较少,只有磁盘块大小、磁盘块数量、数据区开始位置、根目录文件开始位置等。typedefstructBLOCK0//引导块内容{//存储一些描述信息,如磁盘块大小、磁盘块数量、最多打开文件数等、charinformation[200];unsignedshortroot;//根目录文件的起始盘块号unsignedchar*startblock;//虚拟磁盘上数据区开始位置}block0;4.全局变量定义(1)unsignedchar*myvhard:指向虚拟磁盘的起始地址(2)useropenopenfilelist[MAXOPENFILE]:用户打开文件表数组(3)useropen*ptrcurdir:指向用户打开文件表中的当前目录所在打开文件表项的位置;(4)charcurrentdir[80]:记录当前目录的目录名(包括目录的路径)(5)unsignedchar*startp:记录虚拟磁盘上数据区开始位置5.虚拟磁盘空间布局由于真正的磁盘操作需要涉及到设备的驱动程序,所以本实例是在内存中申请一块空间作为虚拟磁盘使用,我们的文件系统就建立在这个虚拟磁盘上。虚拟磁盘一共划分成1000个磁盘块,每个块1024个字节,其布局格式是模仿FAT文件系统设计的,其中引导块占一个盘块,两张FAT各占2个盘块,剩下的空间全部是数据区,在对虚拟磁盘进行格式化的时候,将把数据区第1块(即虚拟磁盘的第6块)分配给根目录文件,如图3-3所示:引导块FAT1FAT2数据区块数1块2块2块995块图3-3虚拟磁盘空间布局五,系统详细设计、1,格式化磁盘//磁盘格式化函数voidmy_format(){block0*b0;unsignedchar*p;fat*fat1,*fat2;inti;fcb*root,*root0;time_trawtime;structtm*timeinfo;FILE*fp;printf(Startformatfilesystem...\n);//将虚拟磁盘第一个块作为引导块b0=(block0*)myvhard;//文件系统的魔数memcpy(b0-magic_number,10101010,8);//文件系统的描述信息strcpy(b0-infomation,MyFileSystemV1.0\n);b0-root=5;b0-startblock=myvhard+5*BLOCKSIZE;//建立两张完全一样的FAT表p=myvhard;fat1=(fat*)(p+BLOCKSIZE);//第1个块fat2=(fat*)(p+3*BLOCKSIZE);//第3个块for(i=0;i5;i++){//前5个块是设置为已分配fat1[i].id=END;fat2[i].id=END;}for(;iSIZE/BLOCKSIZE;i++){//后995个设置为空闲fat1[i].id=FREE;fat2[i].id=FREE;}fat1[5].id=END;//根目录文件使用fat2[5].id=END;//创建根目录文件root,将数据区第1块(即虚拟磁盘的第6块)分配给根目录文件//在该磁盘块中创建两个特殊的目录项:“.”和“..”,其内容除了文件名不同之外,其他字段完全相同p+=5*BLOCKSIZE;root=(fcb*)p;memset(root,0,BLOCKSIZE);//创建目录项'.'strcpy(root-filename,.);//根目录文件名strcpy(root-exname,di);//根目录文件拓展名root-attribute=0;rawtime=time(NULL);//获取时间,以秒计,从1970年1月1日起算,存于rawtimetimeinfo=localtime(&rawtime);//转为当地时间root-time=timeinfo-tm_hour*2048+timeinfo-tm_min*32+timeinfo-tm_sec/2;//文件创建时间root-date=(timeinfo-tm_year-80)*512+(timeinfo-tm_mon+1)*32+timeinfo-tm_mday;//文件创建创建日期root-first=5;//文件起始盘块号root-length=2*sizeof(fcb);root-free=1;//复制目录项'.'为'..'root0=root+1;memcpy(root0,root,sizeof(fcb));strcpy(root0-filename,..);root0++;for(i=2;i(int)(BLOCKSIZE/sizeof(fcb));i++){strcpy(root0-filename,);root0++;}//写入文件fp=fopen(filename,w);fwrite(myvhard,SIZE,1,fp);fclose(fp);update_openfilelist0();printf(Formatfilesystemok.\n);}2,创建目录a)调用do_read读入当前目录文件到内存,检查新建文件目录是否重名b)分配一个空闲的打开文件表项c)分配一个空闲的盘块d)在当前目录中问新建目录寻找一个空闲的目录项e)设置FCB,文件的属性信息f)创建特殊的两个目录项‘.’,‘..’g)返回//创建子目录voidmy_mkdir(char*dirname){intfilelen;fcb*fcbptr,fcbtmp,fcbtmp0;chartext[MAX_TEXT_SZIE],*p;inti,fd;unsignedshortnumOfBlock;unsignedchar*blockptr;time_trawtime;structtm*timeinfo;fat*fat1;fat1=(fat*)(myvhard+BLOCKSIZE);//调用do_read()读入当前目录文件内容到内存openfilelist[currfd].count=0;filelen=do_read(currfd,(int)openfilelist[currfd].length,text);fcbptr=(fcb*)text;//检查当前目录下新建目录文件是否重名for(i=0;i(int)(filelen/sizeof(fcb));i++){if(strcmp(dirname,fcbptr-filename)==0){printf(Error:thedirnameisalreadyexist.\n);return;}fcbptr++;}//为新建子目录文件分配一个空闲打开文件表项fd