1、其中,存放的文件都为简单的TXT文本,即字符型文件。运行程序的基本要求:编写一个shell程序。该程序能像cmd.exe一样,能对你所构造的文件系统进行目录和文件操作。要求实现地功能包括:cd、dir、mkdir,more,copy,rmdir,find,attrib,copy,del,xcopy,exit等几个ms-dos命令。实习步骤:1. 首先理解该课程设计的要求,弄清楚shell的各种操作,查找各种资料,明白一个多级目录的文件系统是什么样的,加深理解文件系统的组成以及各种内部结构。2. 通过查找各种资料来搞清楚文件系统的存储形式,写出相关的结构体定义以及大体框架结构。3. 编写各个功能
2、的代码函数来实现shell程序中目录与文件的操作。在基本的功能都实现以后对写出的程序进行一些必要的调试和修改,在此过程中找出问题并改正。4. 运用学过的多线程的方法将该程序改为多线程实现的shell程序。5. 总结经验,书写相关的实习报告书实习方法:1. 理解文件系统存储结构,查找多级存储结构文件系统的相关资料,常见的UNIX实现了层次结构化文件的系统。在该方案中,目录中可以包含多个文件和子目录。磁盘被分成多个区。每个分区有自己的文件系统。如下图所示,矩形代表目录,圆圈代表文件,在UNIX操作系统中,目录也被当作文件。它认为目录是单个文件或多个文件。2. UNIX文件系统的中心概念是超级块su
3、perblock, i节点inode,数据块data block,目录块directory block,和间接块indirection block。超级块占用第1号物理块,是文件系统的控制块,超级块包括:文件系统的大小、空闲块数目、空闲块索引表、空闲i节点数目、空闲i节点索引表、封锁标记等。超级块是系统为文件分配存储空间、回收存储空间的依据。i节点包括除了名字外的一个文件的所有信息,名字与i节点数目一起存在 目录中。结合上图,可以对下图进行理解:3. 磁盘的大小是固定的并且存储是连续的,所以用一个固定大小的文本文件来代表一个磁盘分区,并通过对此文本的内容读写来模拟shell程序中该文件系统中文
4、件和目录的访问和操作。若不存在该文本,则必须对其初始化,形成一个根目录。初始化的操作有:初始化超级块(代表一个根目录)Init_SuperBlock();初始化i结点 Init_INode(); 初始化数据块 Init_DataBlock();4. 模拟对磁盘的访问,通过对文件进行文件seekp定位操作来实现,固定文件的大小由起初写入的文本决定,二进制文件编码是变长的,它灵活,存储利用率高,所以以二进制读写的方式来对本文进行操作。5. 用多线程的方法来实现shell程序,第一个用来接受命令,第二个用来解析命令,第三个用来实现命令。实现的关键点是在定义互斥量和信号量, 并在三个线程中来进行所需的
5、P、V操作。技术方案:1. 定义相关的结构体:/超级块typedef struct int MaxSize; /文件系统的大小 int FirstINodeBlk; /第一个I结点块号 int FirstDBlk; /第一个数据块号 int BlockSize; /每个物理块大小 bool INodeStatusINODES; /INode状态(空闲或占用) bool DataBlockStatusDATABLKS; /数据块状态(空闲或占用)SuperBlock;/i结点 typedef struct int FileType; /文件类型 int INodeNumber; /i-node号
6、 int LinksNum; /链接数 int FileSize; /文件大小 int blocks4; /占用的数据块INode;/目录结构,结构体大小为16Btypedef struct DirectoryItem /INode号 char FileName12; /文件名DirectoryItem;2. 声明各种函数(所实现的相关功能):/Command.hvoid PrintCurPath(); /输出当前路径void SplitCmd(char *Cmd,char *cmd,char *config);/对命令进行分割void mkdir(char *config); /新建一个目录
7、 void more(char *config); /逐屏显示输出void dir(char *config); /显示目录中的文件和子目录void help(char*config); /帮助void cd(char*config); /显示或改变当前目录void rm(char*config); /删除一个目录void format(); /格式化磁盘void InterpretCmd(); /对命令解析/SuperBlock.hvoid Init_SuperBlock(); /初始化超级块void WriteSuperBlock(); /写超级块到文件中void ReadSuperBlo
8、ck(); /从文件中读取超级块/INode.hvoid Init_INode(); /初始化i结点int AllocINode(); /申请I-结点void WriteINode(int,INode); /写I-结点到文件中void ReadINode(int,INode&); /从文件中读取I-结点void FreeINode(int); /释放I-结点void SetDirINode(INode&, int,int); /初始化新建的目录I-结点void SetFleINode(INode&,int,int ,int*,int); /初始化新建的文件I-结点void UpdataINod
9、e(int); /更新I-结点/Directory.hbool HaveSameName(char *,INode); /寻找是否有相同的文件名bool FindDir(char *,INode, int, DirectoryItem& /查找目录项void SetDirItem(char *c,int,DirectoryItem& /初始化新建的目录项void WriteDir(INode,DirectoryItem,int); /写目录项void ReadDir(int,INode,DirectoryItem & /读目录项/DataBlock.hvoid Init_DataBlock()
10、; /初始化数据块int AllocDBlk(); /申请数据块void WriteDBlk(int *,int,char *); /释放数据块void FreeDBlk(int); /写数据块3. 必要的初始化操作:/初始化超级块void Init_SuperBlock() superblock.MaxSize=240*BLKSIZE; superblock.BlockSize=BLKSIZE; superblock.FirstINodeBlk=FIRSTIBLK; superblock.FirstDBlk=FIRSTDBLK; for(int i=0;iINODES;i+) superbl
11、ock.INodeStatusi=true; for(i=0;DATABLKS; superblock.DataBlockStatusi=true; /0号I-结点的被根目录使用,0号数据块被根目录使用 superblock.INodeStatus0=false; superblock.DataBlockStatus0=false; fstream fout; fout.open(A.txt,ios:out|ios:binary); if(!fout) coutCant open this fileendl; exit(0); fout.write(char*)&superblock,FIRS
12、TIBLK*BLKSIZE); fout.close();/初始化I-结点void Init_INode() inodei.FileType=UNKNOW; inodei.INodeNumber=i; inodei.LinksNum=0; inodei.FileSize=0; for(int j=0;j4;j+) inodei.blocksj=-1; /0号I-结点被根目录占用,0号数据块被根目录使用 inode0.FileType=ISDIR; inode0.blocks0=0; inode0.LinksNum=2;in|ios: fout.seekp(FIRSTIBLK*BLKSIZE);
13、 for( i=0; fout.write(char*)&inodei,sizeof(INode);/初始化数据块 void Init_DataBlock() fout.seekp(FIRSTDBLK*BLKSIZE); /初始化根目录 DirectoryItem RootDir2; strcpy(RootDir0.FileName,. RootDir0.INodeNumber=0; strcpy(RootDir1.FileName,. RootDir1.INodeNumber=0;2;RootDiri,sizeof(DirectoryItem); foutsetw(DATABLKS*BLKS
14、IZE-1-sizeof(DirectoryItem)*2)0;4. 定义多线程实现的互斥量和信号量初始化互斥量与信号量:HANDLE mutex; /一个互斥量HANDLE ghSemaphore1, ghSemaphore2, ghSemaphore3; /三个信号量mutex = CreateMutex( NULL,FALSE,NULL); /初始化未被占用ghSemaphore1 = CreateSemaphore( NULL, 1,1,NULL); /初始化最大资源值与可利用资源都为1ghSemaphore2 = CreateSemaphore( NULL, 0,1,NULL); /
15、初始化可利用资源为0,最大资源值为1ghSemaphore3 = CreateSemaphore( NULL, 0,1,NULL);5. 整体流程图及重要功能函数的说明和流程图1) 整体流程图:2) 创建目录:3) 删除操作del:4) 改变当前目录:5) 创建文件:实习结果:1. 进入运行界面:2. 显示所能实现的功能3. 使用mkdir创建目录:4. 显示当前文件5. 进入yuanyuan目录6. 返回上一级:7. 删除yuanyuan目录8. 显示当前目录:9. 创建一个文件并输入内容:10. 显示当前文件的内容:11. 格式化:12. 退出程序:实习分析: 通过本次的课程设计,使我能够
16、正确运用操作系统课程中所学的基本理论和知识,加深了对文件系统基本概念的理解,以及磁盘文件系统的文件操作。设计一个软件,先要做好思路分析,这一点很重要,如果没有分析好思路,那么就会觉得思维混乱且无从下手,还有比较重要的是,需要先仔细画好流程图。在程序设计的开始,由于分析工作做得不够深入和细致,出了很多的错误。另外在运用C+的时候,感觉有点生疏,在编程和调试的过程中,经常会出现意想不到的问题,并非每个问题都可以从相关资料中找到解决方法,有些问题是由于自己的马虎所导致的,这就需要通过仔细的分析来解决问题。 在设计过程中,查询了不少相关资料,不断的发现问题、提出问题、解决问题。在对自己所编写的源程序段的纠错的过程中,使我更好的理解了操作系统中文件系统的理论知识,同时又把学到过的多线程加入到程序中来实现多线程方式的shell程序,让我对多线程的思想又有了更深一步的理解。总的来说通过这次课程设计使我学到了很多在平时的学习中学不到的很多东西,通过这次课程设计,使我对操作系统和编程产生了兴趣。我相信,只要不断的严格要求自己,注意培养自己的思维能力,就一定会有所收获和提高。