1、一、 实验内容1、 题目:模拟UNIX(linux)文件系统 问题描述在任一OS下,建立一个大文件,把它假象成一张盘,在其中实现一个简单的 模拟UNIX文件系统 。 二、 概要设计 在现有机器硬盘上开辟20M的硬盘空间(利用一个循环操作,在Disk中写入20M的零,创建一个20M的文件即是),作为设定的硬盘空间。空闲盘块栈(存放空闲盘块)目录区 各盘块(每个占1KB)存放文件内容,为程序设计方便,iNode节点也存放在此处。1kb(目录快)30kB20480kb0kb(超级块信息)磁盘块物理模型如下文件则是指具有文件名的若干相关元素的集合。文件属性主要如下文件名:实现了按名存取,文件名和目录文
2、件允许重名。文件类型:可以从不同的角度来规定文件的类型。普通文件、管道文件、块文件。文件长度:指文件的当前长度,长度的单位可以是KB。文件的物理位置:文件在磁盘中物理的存储,并打印出来。此次UNIX文件系统最简单的目录结构。整个文件系统中只建立一张目录表,每个文件一个目录项,目录项含有文件相关信息。每建立一个新文件要先检索所有的目录项保证文件名唯一。然后找出一空白目录项填入相关信息,并修改状态位。删除文件是找到对应目录项,回收所占用空间,清除该目录。逻辑结构如下文件名索引节点编号文件名1INode文件名2INode文件名3INode. .Unix文件系统当文件很多时,文件目录要占用大量的盘块。
3、在查找目录的过程中,可能需要多次启动磁盘读入目录文件的盘块。在检索目录文件中只用到了文件名,显然,文件的物理地址等文件的描述信息在检索目录时不需调入内存。为此,可以把文件名与文件描述信息分开。使文件描述信息单独形成一个索引结点。把文件描述信息单独形成一个称为索引结点的数据结构,简称为inode;文件目录中的每个目录项,则仅由文件名及指向该文件所对应的inode的指针所构成。这样,为找到一个文件的平均启动磁盘的次数减少很多模型如下: RootFan.txtINode节点INode节点目录节点节点AB 存储空间的分配与回收成组链接法首先,建立操作系统课程的设计模型。这个系统将利用一个20M的文件作
4、为自己的磁盘空间,设计时由于一个盘块占用1KB,所以20M空间可以产生20480个盘块系统本身将0# - 30#块作为系统区,所以用户区便剩下20450个盘块,每50个盘块为一组,一共可以分为409个组。将每一组含有的盘块总数N和该组的盘块号,记入其前一组的第一个盘块的S.free(1)S.free(50)。这样由各组的第一个盘块形成了一条链。将第一组的盘块总数和所有的盘块号,记入空闲盘块号栈中,作为当前可供分配的空闲盘块号。最末一组只有49个盘块,其盘块号分别记入其前一组的S.free(1)S.free(99)中,而在S.free(0)中则存放0,作为空闲盘块链的结束标志。基本功能 1、初始
5、化 2、建立文件 3、建立子目录 4、打开文件 5、删除文件 6、删除目录 7、显示目录三、 详细设计和编码 正规文件 i 结点文件类型 目录文件 (共1byte) 块设备 管道文件 。物理地址(索引表) 共有13个表项,每表项2byte 。文件长度 4byte 。联结计数 1bytestruct INodeFileSpec fileSpec;short iaddr13;int fileLength;int linkCount; 文件名 14byte(5)目录项信息 i 结点号 2bytestruct DirChild char filename14; short i_BNum ;struct
6、 DirNodeDirChild childItem64;shortDirCount;定义磁盘文件名const char FileName=os.txt;默认为空的文件名const char NullName=0000000000000;默认目录文件的长度const int DirLen=1; 默认超级块的快号const short SSNum=-1;/super block num定义枚举类型,普通,目录,块文件,管道文件enum FileSpecNORMAL,DIR,BLOCK,PIP;/0,1,2,3short SS51;/超级栈,指针为SS0,保存当前可用盘快short freeBlo
7、ckNum=0;/当前可用盘快所在组记录的盘快号short freeTotalB=20450;文件总长度short freeDirNode29;/可用索引节点栈short freeDirCount=30;/索引节点栈指针short currDirNum;/当前目录所在的磁盘号short currINum;DirNode *currDir;/当前目录节点INode*iNode; /当前iNode节点系统调用函数列表 系统调用原型功能入口、出口参数说明Void ArrarEqual(short arr51,short begin,short end)arr51数组赋值,在成组链接初始化时使用voi
8、d BWrite(short arr51,short diskNum)往磁盘中写入短数组void BWriteArr(short arr512,short diskNum )重构BWrite,实现一个数组的写入,数组长度不确定void BRead(INode *iNode,short diskNum)从磁盘中读出iNode节点void BRead(short arr51,short diskNum)从磁盘中读出数组void BReadArr(short arr512,short diskNum)从磁盘中读出数组,成组链接多级索引使用BWrite(DirNode *currDir,short d
9、iskNum)写入一个目录项Void BWrite(INode *iNode,short diskNum)写入一个iNodeVoid AssAnEmpty()分配一个空闲的普通快short AssAnDir()分配一个空闲的目录快short IsFileExist(DirNode *currDir,char fileName14)判断一个文件是否存在-1不存在,否则返回文件所在磁盘号bool IsFile(INode *iNode,short diskNum)判断一个文件是一个普通文件bool IsDir(INode *iNode,short diskNum)判断一个文件是一个索引文件void
10、 CreateINode(INode *iNode,FileSpec fileSpec,short linkCount,short length)创建一个iNode,并分配磁盘空间void CleanINode(INode *iNode)清空iNode信息,并分配磁盘空间void InsertDir(DirNode *currDir,char fileName14,short blockNum)将当前目录项插入到内存中目录项中void ShowFileInfo(INode *iNode,char fileName14)打开一个文件,显示文件信息void ShowBlockInfo(INode
11、*iNode)打开一个文件,显示文件占用磁盘空间信息void DelDirItem(DirNode *currDir,char fileName14)删除索引中一项void CallBackOne(short diskNum)回收一块空余磁盘片void CallBackINode(short diskNum)回收文件的iNOde节点主要函数列表函数原型功能入口、出口参数说明Format创建20M磁盘void Init(DirNode *currDir,FileSpec fielSpec,char filename14,INode *iNode,short diskNum)初始化,创建个目录节点
12、并初始化超级栈Init()初始化索引栈void Linkdisk()成组链接初始化void InitCreate(DirNode *currDir,FileSpec fielSpec,char filename14,INode *iNode,short diskNum)创建一个文件节点,并分配INOde和磁盘空间void Create(DirNode *currDir,char fileName14,INode *iNode,short length,FileSpec fileSpec)存在文件,并分配iNOde节点和磁盘空间void Mf(DirNode *currDir,char file
13、Name14,INode *iNode,short length)创建一个文件void Md(DirNode *currDir,char fileName14,INode *iNode,short length)在当前目录创建一个子目录void Open(DirNode *currDir,char fileName14,INode *iNode)打开文件,显示文件信息void Del(DirNode *currDir,char fileName14,INode *iNode)删除一个文件void Rd(DirNode *currDir,char fileName14,INode *iNode)
14、删除一个目录void Dir(DirNode *currDir,INode *iNode)显示目录项的内容void exit(DirNode *currDir,INode *iNode)退出,并销毁资源void AuthorMessage()打印版权信息void help()提示信息主框架开 始打印作者信息初始化磁盘合法性检查输入命令显示:命令错误falseo有新建文件新建目录打开文件删除文件删除目录显示目录立退出初始化命令format 利用文件创建命令可在硬盘上创建一个名为Disk的20M的空间,并将该磁盘空间整体假想成一个独立硬盘,我们将在这张封闭的磁盘上进行各种关于文件的操作。Forma
15、t 具体操作如下:(1) 利用一个循环操作,在Disk中写入20M的零。(2) 然后将0#块,即超级块中写入31# - 80#的盘块号,并将全部可用剩余盘块数FreeBlock=20450记录在0#块中。(3) 同时将80#,130#,180#(间距50)等408个(第409个组头不存在下一组)盘组的组头中写入成组连接好的下一组盘块号。2、系统初始化自动完成假如Disk已被格式化完毕,那么系统便将进行下一步,那就是初始化。初始化主要完成将根目录项读入内存,便于文件操作,并将0#超级块中保存的当前可用盘块号写入内存中的超级栈中,具体操作如下:(1) 初始化一个超级栈,将超级块中保存的当前可分配盘
16、块号读入栈中。(2) 定义一个全局变量FreeBlock,用来记录当前全部可用的盘块总数。3、建立文件mf filename如果终端发来的命令格式为mf filename,则可以判断出这是建立文件的命令。要想成功建立一个文件,首先需要判断在同级目录下是否有重名的文件,并且需要判断是否有足够的空间允许建立一个指定长度的文件。mf(代表make file)具体操作如下: (1) 判断所要建立的文件是否重名。首先将终端输入的文件名filename在RootDir640进行检索,看是否可以找到相同的名字,假如找到了相同的名字还不能立刻判断是重名了,因为同级目录下允许文件夹与文件重名,然后利用DirIt
17、em结构中的最后2个Byte要找到暂时重名文件的i结点,从i结点中读出该文件的属性,看是为正规文件还是文件夹。如果重名了,系统会提示,否则进行下一步。 (2) 如果不重名,则要根据用户输入的文件长度来判断当前的剩余盘块总数是否足够分配,这项工作不仅仅是用终端输入来的length与剩余盘块总数FreeBlock比较,因为Unix本身采取混合索引方式,所以根据文件的长度会分配不同的索引盘块数。所以判断盘块数是否足够同时要计算出相应的索引盘块数。如果文件数据本身盘块数加上相应的索引盘块数不会超过总剩余盘块数,则可进行分配。开 始获得文件名获得文件长度合法性检查返 回分配目录项分配磁盘空间分配索引节点
18、返 回4、建立子目录md filename建立子目录,即建立一个文件夹。其可以看作是建立文件的一个特殊情况,建立一个文件夹的过程和上述的建立文件非常相似,也要判断重名,也要判断是否盘块数足够分配,以及分配时所要考虑到的全部情况(文件夹利用0级索引)。 开 始获得目录名读取目录节点合法性检查返 回创建iNode,分配索引节点分配磁盘空间分配目录项返 回5、 打开文件open filename(显示文件所占的盘块)开 始检查当前目录目录中有文件么?检查iNode文件属性与操作类型相符?打开文件:显示文件信息打印iNode中盘快信息显示:“打开”成功返 回显示:不存在该文件,打开失败返 回显示:文件
19、类型不匹配返 回有无否是读取iNode(a) 这个命令就是所谓的读文件命令,在这个模拟Unix的系统中,我们将显示文件所占的盘块以及文件的相关信息。要打开文件,当然首先要判断是否有这样一个文件名,然后才是读出全部的盘块数 6、 删除文件del filename开 始查该用目录表currDircurrDir中有该文件?是显示:文件已撤消检查iNode返 回文件类型匹配?是否归还文件所占的存储区域在UFD中清除该文件登记栏在清除iNode信息,释放磁盘节点返 回currDir中清除该文件的登记栏 删除文件同创建文件都是非常复杂的操作,要有多种情况需要考虑。要想成功删除一个文件,首先需要判断在同级目
20、录下是否有该文件名,然后在根据该文件为几级索引文件进行相应的回收 7、 删除目录rd filename就如同建立目录好似建立文件的一种特殊情况,删除目录也和删除文件差不多,但是有一点是绝对不同的,要特别注意。当子目录下建立了文件或者文件夹时,即表示子目录不为空,那么系统本身为了保持数据的完整性,是不对该目录进行删除操作的,而提示用户该目录不为空。除非用户删除了该目录下的全部文件后,返回到根目录,此时子目录为空,才允许系统删除该文件夹。删除时的具体过程同删除0级索引文件极为相似,这里就不作过多说明。文件流程如删除文件,此处不再赘述。8、 显示目录dir(即显示目录下的信息,包括文件、子目录等)D
21、ir是一个很容易实现的命令,在目录下输入此命令,即可以获得目录下的信息,包括文件、子目录等。 开 始读取当前目录读取iNode显示完所有目录显示文件信息打印iNode中显示:成功返 回否是 11、正常退出指令exit不要小看了这条指令,它可以帮你完成许多被你遗忘的操作,由于此次代码编写超过了3000行,而且涉及到大量的文件操作函数,所以难免会对文件的关闭,栈的释放等结束工作考虑不周全,为了提高数据的可靠性与完整性,建议退出系统时用此命令,它可以自动完成文件的关闭。程序源代码#include #include #include using namespace std;const char Fil
22、eName=os.txt;const char NullName=0000000000000;const int DirLen=1; const short SSNum=-1;/super block numenum FileSpecNORMAL,DIR,BLOCK,PIP;/0,1,2,3/i节点结构信息struct INodeFileSpec fileSpec;short iaddr13;int fileLength;int linkCount;struct DirChild char filename14; short i_BNum ;struct DirNodeDirChild chi
23、ldItem64;shortDirCount;short SS51;/超级栈,指针为SS0short freeBlockNum=0;/当前可用盘快所在组记录的盘快号short freeTotalB=20450;short freeDirNode29;/可用索引节点栈short freeDirCount=30;/索引节点栈指针short currDirNum;/当前目录所在的磁盘号short currINum;DirNode *currDir;INode*iNode; /=/函数描述:创建20M磁盘/入口参数:无/返回值:无/=void Format()cout系统正在初始化.endl;/ 打开
24、文件FILE *f = fopen(FileName,w+);if (f = NULL)cout程序创建错误,请重新输入endl;return ;for(int i=0;i20971520;i+)/20971520=20Mb,暂时2mb fprintf(f,%c,0);/ 关闭文件fclose(f);/=/函数描述:数组赋值/入口参数:无/返回值:无/=void ArrarEqual(short arr51,short begin,short end)for(short i=0;iend-begin+1;i+)arr50-i=begin+i;/=/函数描述:数组赋值/入口参数:无/返回值:无/
25、=/*void BWrite(short arr51,short diskNum)FILE *f = fopen(FileName, r+);if (f = NULL)cout写文件处错误,请重新输入endl;return ;/设置文件指针if(fseek(f,1024*diskNum,0)cout文件指针错误endl;fwrite(arr,sizeof(short),51,f);fclose(f);*/=/函数描述:重构BWrite,实现一个数组的写入/入口参数:无/返回值:无/=void BWrite(short arr51,short diskNum )FILE *f = fopen(F
26、ileName, r+);if (f = NULL)cout写文件处错误,请重新输入endl;return ;/设置文件指针if(fseek(f,1024*diskNum,0)cout文件指针错误endl;fwrite(arr,sizeof(short),51,f);fclose(f);/=/函数描述:重构BWrite,实现一个数组的写入,数组长度不确定/入口参数:无/返回值:无/=void BWriteArr(short arr512,short diskNum )FILE *f = fopen(FileName, r+);if (f = NULL)cout写文件处错误,请重新输入endl;
27、return ;/设置文件指针if(fseek(f,1024*diskNum,0)cout文件指针错误endl;fwrite(arr,sizeof(short),512,f);fclose(f);/=/函数描述:重构BWrite,实现一个数组的写入/入口参数:无/返回值:无/=void MyBWrite(short arr51,short diskNum )FILE *f = fopen(FileName, r+);if (f = NULL)cout写文件处错误,请重新输入endl;return ;/设置文件指针if(fseek(f,1024*diskNum,0)cout文件指针错误endl;
28、for(short i=0;i51;i+)fprintf(f,%d,arri);fclose(f);/=/函数描述:从磁盘中读出数组/入口参数:无/返回值:无/=void MyBRead(short arr51,short diskNum)FILE *f = fopen(FileName, r+);if (f = NULL)cout读文件处错误,请重新输入endl;return ;/设置文件指针if(fseek(f,1024*diskNum,0)cout文件指针错误endl;for(short i=0;i51;i+)fscanf(f,%d,&arri);fclose(f);/=/函数描述:从磁
29、盘中读出iNode节点/入口参数:无/返回值:无/=void BRead(INode *iNode,short diskNum)FILE *f = fopen(FileName, r+);if (f = NULL)cout写文件处错误,请重新输入endl;return ;/设置文件指针if(fseek(f,1024*diskNum,0)cout文件指针错误fileLength);int temp=int(fgetc(f);switch(temp)case 0:iNode-fileSpec=NORMAL;break;case 1:iNode-fileSpec=DIR;break;case 2:i
30、Node-fileSpec=BLOCK;break;case 3:iNode-fileSpec=PIP;break;fread(iNode-iaddr,2,13,f);fscanf(f,%d,&iNode-linkCount);fclose(f);/=/函数描述:从磁盘中读出数组/入口参数:无/返回值:无/=void BRead(short arr51,short diskNum)FILE *f = fopen(FileName, r+);if (f = NULL)cout读文件处错误,请重新输入endl;return ;/设置文件指针if(fseek(f,1024*diskNum,0)cou
31、t文件指针错误endl;fread(arr,sizeof(short),51,f);fclose(f);/=/函数描述:从磁盘中读出数组, 放入到iNOde中/入口参数:无/返回值:无/=void BReadArr(short arr512,short diskNum)FILE *f = fopen(FileName, r+);if (f = NULL)cout读文件处错误,请重新输入endl;return ;/设置文件指针if(fseek(f,1024*diskNum,0)cout文件指针错误endl;fread(arr,sizeof(short),512,f);fclose(f);/=/函
32、数描述:写入一个目录项/入口参数:无/返回值:无/=void BWrite(DirNode *currDir,short diskNum)FILE *f = fopen(FileName, r+);if (f = NULL)cout写文件处错误,请重新输入endl;return ;/设置文件指针if(fseek(f,long(1024*diskNum),0)cout文件指针错误endl;for(int i=0;ichildItemi.i_BNum);fputs(currDir-childItemi.filename,f);fclose(f);/=/函数描述:写入一个iNode/入口参数:无/返
33、回值:无/=void BWrite(INode *iNode,short diskNum)FILE *f = fopen(FileName, r+);if (f = NULL)cout写文件处错误,请重新输入endl;return ;/设置文件指针if(fseek(f,1024*diskNum,0)cout文件指针错误fileLength);fputc(iNode-fileSpec,f);fwrite(iNode-iaddr,2,13,f);fprintf(f,%d,iNode-linkCount);fclose(f);/=/函数描述:分配一个空闲的普通快/入口参数:无/返回值:无/=shor
34、t AssAnEmpty()short temp;if(SS01)SS0-;temp=SSSS0+1;/SSSS0+1=-1;freeTotalB-;/总剩余数-1return temp;elseif(SS1=0)cout盘片用尽endl;return -1;temp=freeBlockNum;freeBlockNum=SS1;BRead(SS,SS1);if(temp=0)SS0-;temp=SSSS0+1;/SSSS0+1=-1;freeTotalB-;return temp;/=/函数描述:分配一个空闲的目录快/入口参数:无/返回值:无/=short AssAnDir()if(freeDirCount=0)cout无空余目录节点endl;return -1;elsefreeDir