操作系统模拟UNIX文件系统的设计及实现.docx
操作系统课程设计模拟UNIX文件系统的设计及实现院 系: 计算机学院二系班 级: 计07 -2班姓 名:2009 年 6 月 10 日操作系统课程设计任务书一、题目:银行家算法二、设计要求(1)吴勇克(组长)、刘胜光组成设计小组。(2)小组成员分工协作完成。要求每个成员有自己相对独立的模块,同时 要了解其他组员完成的内容。(3)查阅相关资料,自学具体课题中涉及到的新知识。(4)采用结构化、模块化程序设计方法设计,功能要完善,界面美观。(5)所设计的系统应有菜单、动画和音乐。(6) 按要求写出课程设计报告,并于设计结束后1周内提交。其主要内容 包括:封皮、课程设计任务书,指导教师评语与成绩、目录、概述、软件总体设计、详细设计、软件的调试、总结、谢启、附录:带中文注释的程序清单、参考 文献。报告一律用 A4纸打印,中文字体为宋体,西文字体用 Time New Roma 一律用小四号字,行距采用“固定值”18磅,首行缩进2字符。总体设计应配合软件总体模块结构图来说明软件应具有的功能。详细设计应用传统或N-S流程 图和屏幕抓图说明,调试的叙述应配合出错场景的抓图来说明出现了哪些错误, 如何解决的。三、课程设计工作量由于是设计小组团结协作完成设计任务,一般每人的程序量在200行有效程 序行左右,不得抄袭。四、课程设计工作计划2009年6月15日,指导教师讲课,学生根据题目准备资料;2009年6月16日,设计小组进行总体方案设计和任务分工;2009年16月16日2009年6月23日,每人完成自己承担的程序模块并通 过独立编译;2009年6月23日2009年6月29日,将各模块集成为一个完整的系统, 并录入足够的数据进行调试运行;2009年6月30日,验收、撰写报告;2009年7月2日,验收或总结。指导教师签章教研室主任签章目录1. 概述 12. 总体设计 .23. 详细设计 34. 代码调试 95. 总结116. 附录 127. 参考文献 . 30二概述【课设原理】UNIX采用树型目录结构,每个目录表称为一个目录文件。一个目录文件是由目录项组成的。每个目录项包含16B,一个辅存磁盘块(512B)包含32个目录项。在目录项中,第1、2字节为相应文件的外存i节点号, 是该文件的内部标识;后14B为文件名,是该文件的外部标识。所以,文件目 录项记录了文件内、外部标识的对照关系。根据文件名可以找到辅存i节点号,由此便得到该文件的所有者、存取权、文件数据的地址健在等信息。UNIX的存储介质以512B为单位划分为块,从0开始直到最大容量并顺序加以编号就成了 一个文件卷,也叫文件系统。UNIX中的文件系统磁盘存储区分配图如下:0#2#K#K+1#K+2#K+3#n引导区 管理区T节点区1文件存储区本次课程设计是要实现一个简单的模拟 UNIX文件系统。我们在磁盘中申请 一个二进制文件模拟UNIX内存,依次初始化建立位示图区,I节点区,数据块 区。并给已打开的文件建立文件打开表。【课设内容】1.设计任务 多用户、 logi n logout dir creat多级目录结构文件系统的设计与实现。可以实现下列几条命令 用户登录退出当前用户列文件目录创建文件delet删除文件及目录树ope n close read write mkdir打开文件 关闭文件 读文件 写文件创建目录cd format quit改变文件目录 格式化文件系统 退出文件系统2. 文件系统应具有的基本功能(1-8个用户)(1) 多用户 :usr1,usr2,usr3, ,usr8(2) 多级目录:可有多级子目录;(3) 具有login(用户登录)(4) 系统初始化(建文件卷、提供登录模块)(5) 文件的创建: create(6) 文件的打开:ope n(7) 文件的读:read(8) 文件的写:write(9) 文件关闭:close(10) 删除文件或目录:delet(11) 创建目录(建立子目录):mkdir(12) 改变当前目录:cd(13) 列出文件目录:dir(14) 退出:logout.总体设计【算法思想】先建立512个块,每个块对应512个字节,在建立一个有512个元素的字符数组, 每个元素 对应相应的块号,不管是文件或是目录都有I节点,建立自己设定数目元素的I节点表,并依次把位图区,I节点表,数据块区每个元素映射到一个二进制文件上。在每一次的操作中 如果相应元素有变动,则对应在文件中更新输出相应数据,以便下一次启动程序的时候可以快速导入上一次的数据。【系统总体框架图】©(0pbitmap51卅temp fO24B32个位El512Bi节点32T数据区$12埃【系统总体流程图】开始在内存中申请内存空间 将磁盘上的文件读入内存N执行 format()*建立文件系统用户登录模块,输入用户名和密码,可以 .在程序中设定,不用保存在文件系统中执行init(),进行初始化操作,进入用户子目录执行command。,对用户输入的命令进行解析和 执行。若数据被修改或新建立,则保存主存i节点和数据块的内容到内存的文件系统,并写回磁 盘,保存修改。若输入错误命令则显示岀错信息三详细设计【各模块功能说明】1. format 模块功能:格式化文件系统,即初始化文件系统,相当于硬盘的格式化。将其中原 有的用户及用户下的文件系统全部还原初始状态,即没有任何用户和目录、文件, 也就是按设计的文件系统格式重建新的文件系统。2. get_blknum 和 release_blk模块功能:get_blk num找到一个空闲数据块,并修改对应位图号元素为1。release_blk修改对应的位图元素,并把文件系统中对应的数据块清零。3. init() 模块功能: 读入文件系统4. quit()模块功能:退出系统5 .creat(模块功能: 创建文件,分配一空目录项,分配磁盘块。可用位示图。填写该空目录 项。如文件长度( 0),文件名,类型等。6. ope n(模块功能:打开文件,并判断文件类型和打开方式。 如果文件没有在文件打开表中就 在文件打开表中建立该文件项。7. close(模块功能: 关闭文件,删除该文件的用户打开文件表目。8. write()模块功能:写文件 ,需要先打开文件。并判断文件权限。写完后修改文件系统中的对应 数据区。9. read(模 块功能:读文件。需先打开文件。 读入相应数据块的内容到缓冲区, 然后输出。10. delet()模 块功能: 如果参数是文件则删除文件, 如果是目录则删除该目录下的所有文件和 目录。11. mkdir()功能:建立新的目录 ,先在 I 节点表中找到一个未使用的,并初始化该 I 节 点,并在文件系统中对应更新输出。12. cd()功能:将当前目录切换到当前目录的一个子目录下或当前目录的父目录。程序流程图各功能模块流程图用户登陆login()初始化函数init()开始读入位示图信息到内存1F读入i节点信息到内存1r当前目录为根目录1r初始化打开文件表1r结束改变当前目录cd()开始argv1=.否遍历i节点区录是否存在否找到的目录i节点号送当前目录 inum cur丄结束是Ar当前目录的父 i 节点号送当前目录 inum cur创建目录mkdir()打开文件open()读文件read()iP遍历i节点区.开始;提示输入打开模式*将打开文件信息写入打开 文件信息表四.代码调试1.初始化和登陆文件系统 第一次运行程序ISB C AEJev-C pexeLogin:adninCanfC open File usep-txt.This fll&svstem not exist, it uill heUill be to Formati £ Hes</stenk_ -.HARMING:ALL MTA OH THIS FILESVSTEH UILL RE LOST* Proceed with Fovmat<V?VPilesystem created successFulPlease F irst login * Login:adnin pass:Mc»rd - *Do Dii 'uant; creat a nev? user?<Zn : j;2建立新目录,显示当前目录下的文件和目录,并转到新目录下EB C:Dev-C ppI® l eapLadmln$nkdir a Adminl$dira<DJK>ftdmin l$c<i a admin /a $_(J flle<S>10 Jbj/tes1048576FreeSpace3.建立新的文件,打开,写,读EJ C :Dev<ppAJIL exeadmin/a J$cd badmin/abHcreate ab«txtadmln/a/bHopen ah. txtPlease input open na de : <1: read, 2: write 3: read, and:3Open F ilje ab. txt by Pead and write.idininayblwrite ab .txtThe length of ah.txt; ;0T nput the dit a<CTRLZ to end?: sdkfjhsdksd”诞 edfsdrzLadmin/aZbliad ah. txtTile Length of ab_txt :22 .sdkf jhsdlf?(Aewfsdf sdadmin/ahl$4.clear清屏后,dir查看当前目录下文件信息C:De v -C ph工程丄.eaeadmln/a/Jb>ah txt22 byte sadminZa/fc J$1 filets) 8 di?<s)22 hiites1048554 biftes Fi*ee£pace5.返回根目录下,并删除根目录下所有子目录和文件HJ CADcv-Cpp -.Ifll .extadmin Za/b 1 $cd radmin/- $cd Admin l$delet a idinin lidit*B fileCs> ft dip<s>0 bytes1048576 bytes FreeSpaceadnin $6.logout 退出登录或 quit 退出程序五. 总结开始第一天构思, 不断的筛选证明模拟 UNIX 下的内存方法, 并在网络上查 找相应的 UNIX 环境资料。 接下来几天开始实践动手, 从整体框架开始构思, 到 各个细节端口的实现。操作系统是计算机科学与技术专业中的一门重要基础课, 目的是让我们了解 操作系统的基本概念, 理解计算机系统的资源如何组织, 操作系统如何有效地管 理这些系统资源,用户如何通过操作系统与计算机系统打交道。通过课程设计, 可以进一步理解在计算机系统上运行的其它各类操作系统, 并懂得在操作系统的 支持下建立自己的应用系统。操作系统课程设计,对于训练我们掌握程序设计、 熟悉上机操作和程序调试技术都有重要作用。 重点培养我们的思维能力、 创新能 力和排错能力。通过课程设计,进一步融会贯通教材内容, 掌握程序各功能模块的工作原理, 相互联系和来龙去脉, 完整地建立系统的概念。 激发我的学习热情和主动性, 培 养我的独立工作能力,在实践活动中,将所学知识综合运用,增长才干,并积累 经验。对编程语言又有了更深一层次的认识, 并对编程能力有所加强, 但还是很 多的不足有待改进, 对于编程来说还需要大量的实践, 才能在发现问题和解决问 题中前进与提高。六附录源代码:/ head.h 文件#include <stdio.h>#include <stdlib.h>#include <conio.h>#include <string.h> #include<stack> using namespace std;#define BLKSIZE#define BLKNUM#define INODESIZE#define INODENUM512/ 数据块的大小512/ 数据块的块数32 / i 节点的大小32/ i 节点的数目#define 8 / 打开文件表的数目/用户 typedef struct char user_name10;/ 用户名char password10;/ 密码 User;/i 节点 typedef struct short inum;/ 文件 i 节点号char 10; / 文件名char type;/ 文件类型char user_name10; / 文件所有者short iparent;/ 父目录的 i 节点号short length;/ 文件长度short address2; / 存放文件的地址 Inode;/打开文件表 typedef struct short inum;/ i 节点号char 10; / 文件名short mode;/ 读写模式 (1:read, 2:write,/3:read and write) ;/ 申明函数 void login(void); void init(void); int analyse(char *); void save_inode(int); int get_blknum(void);void read_blk(int); void write_blk(int); void release_blk(int); void pathset(); void del(int);/ 用户命令处理函数 void help(void); void cd(void); void dir(void); void mkdir(void); void creat(void); void open(void); void read(void); void write(void); void close(void); void delet(void); void logout(void); void command(void); void quit();/main.cpp 文件#include "head.h" /定义全局变量charchoice;int argc;/ 用户命令的参数个数char* argv5;/ 用户命令的参数int inum_cur; / 当前目录 chartemp2*BLKSIZE; / 缓冲区 User user; / 当前的用户 charbitmapBLKNUM; / 位图数组 Inode inode_arrayINODENUM; / i 节点数组 ; / 打开文件表数组chari mage_name10 = "data.dat" / 文件系统名称 FILE *fp; / 打开文件指针 创建映像hd,并将所有用户和文件清除void format(void)int i;Inode inode; printf("Will be to format .n");printf("WARNING:ALL DATA ON THIS WILL BE LOST!n");printf("Proceed with Format(Y/N)?");scanf("%c", &choice);getchar();if(choice = 'y') | (choice = 'Y')if(fp=fopen(image_name, "w+b") = NULL)printf("Can't create n", image_name); exit(-1);for(i = 0; i < BLKSIZE; i+)fputc('0', fp);inode.inum = 0;strcpy(inode., "/");inode.type = 'd'strcpy(inode.user_name, "/");inode.iparent = 0;inode.length = 0;inode.address0 = -1;inode.address1 = -1; fwrite(&inode, sizeof(Inode), 1, fp);inode.inum = -1;for(i = 0; i < 31; i+)fwrite(&inode, sizeof(Inode), 1, fp); for(i = 0; i < BLKNUM*BLKSIZE; i+) fputc('0', fp);fclose(fp);/ 打开文件 user.txtif(fp=fopen("user.txt", "w+") = NULL)printf("Can't create n", "user.txt"); exit(-1);fclose(fp);printf(" created successful.Please first login!n"); return ;/ 功能 : 用户登陆,如果是新用户则创建用户void login(void)char *p;int flag;char user_name10;char password10;char 10 = "user.txt"doprintf("login:"); gets(user_name); printf("password:");p=password; while(*p=getch()if(*p = 0x0d)*p='0' /将输入的回车键转换成空格 break;printf("*"); / 将输入的密码以 "*" 号显示 p+;flag = 0;if(fp = fopen(, "r+") = NULL)printf("nCan't open .n", );printf("This not exist, it will be create!n");format();login(); while(!feof(fp)fread(&user, sizeof(User), 1, fp);/ 已经存在的用户 , 且密码正确if(!strcmp(user.user_name, user_name) && !strcmp(user.password, password) fclose(fp); printf("n"); return ;/ 已经存在的用户 , 但密码错误else if(!strcmp(user.user_name, user_name) printf("nThis user is exist, but password is incorrect.n"); flag = 1; fclose(fp); break;if(flag = 0) break;while(flag);/ 创建新用户if(flag = 0)printf("nDo you want to creat a new user?(y/n):"); scanf("%c", &choice);gets(temp);if(choice = 'y') | (choice = 'Y')strcpy(user.user_name, user_name); strcpy(user.password, password); fwrite(&user, sizeof(User), 1, fp); fclose(fp);return ;if(choice = 'n') | (choice = 'N')login();/ 功能 : 将所有 i 节点读入内存void init(void)int i;if(fp = fopen(image_name, "r+b") = NULL)printf("Can't open .n", image_name); exit(-1);/ 读入位图for(i = 0; i < BLKNUM; i+)bitmapi = fgetc(fp);/ 显示位图/ 读入 i 节点信息for(i = 0; i < INODENUM; i+) fread(&inode_arrayi, sizeof(Inode), 1, fp);/ 显示 i 节点/ 当前目录为根目录 inum_cur = 0;/ 初始化打开文件表for(i = 0; i < ; i+)i.inum = -1;/ 功能: 分析用户命令 , 将分析结果填充 argc 和 argv/ 结果: 0-13 为系统命令 , 14 为命令错误int analyse(char *str)int i;char temp20;char *ptr_char;"write","logout",char *syscmd="help", "cd", "dir", "mkdir", "create", "open", "read", "close", "delet", "clear","format","quit"argc = 0;for(i = 0, ptr_char = str; *ptr_char != '0' ptr_char+)if(*ptr_char != ' ')while(*ptr_char != ' ' && (*ptr_char != '0')tempi+ = *ptr_char+; argvargc = (char *)malloc(i+1); strncpy(argvargc, temp, i); argvargci = '0' argc+;i = 0; if(*ptr_char = '0') break;if(argc != 0)for(i = 0; (i < 14) && strcmp(argv0, syscmdi); i+); return i;elsereturn 14;/ 功能 : 将 num 号 i 节点保存到 hd.datvoid save_inode(int num)if(fp=fopen(image_name, "r+b") = NULL)printf("Can't open n", image_name);exit(-1);fseek(fp, BLKNUM +num*sizeof(Inode), SEEK_SET); fwrite(&inode_arraynum, sizeof(Inode), 1, fp);fclose(fp);/ 功能 : 申请一个数据块int get_blknum(void)int i;for(i = 0; i < BLKNUM; i+) if(bitmapi = '0') break;/ 未找到空闲数据块if(i = BLKNUM)printf("Data area is full.n");exit(-1);bitmapi = '1'if(fp=fopen(image_name, "r+b") = NULL)printf("Can't open n", image_name); exit(-1);fseek(fp, i, SEEK_SET);fputc('1', fp);fclose(fp);return i;/ 功能 : 将 i 节点号为 num 的文件读入 tempvoid read_blk(int num)int i, len;char ch;int add0, add1;len = inode_arraynum.length;add0 = inode_arraynum.address0;if(len > 512)add1 = inode_arraynum.address1;if(fp = fopen(image_name, "r+b") = NULL)printf("Can't open .n", image_name); exit(-1);+add0*BLKSIZE,fseek(fp, BLKSIZE+INODESIZE*INODENUMSEEK_SET);ch = fgetc(fp);for(i=0; (i < len) && (ch != '0') && (i < 512); i+)tempi = ch;ch = fgetc(fp);if(i >= 512)fseek(fp,BLKSIZE+INODESIZE*INODENUM+add1*BLKSIZE, SEEK_SET);ch = fgetc(fp);for(; (i < len) && (ch != '0'); i+)tempi = ch;ch = fgetc(fp);tempi = '0'fclose(fp);/ 功能: 将 temp 的内容输入 hd 的数据区void write_blk(int num)int i, len;int add0, add1;add0 = inode_arraynum.address0;len = inode_arraynum.length;if(fp = fopen(image_name, "r+b") = NULL)printf("Can't open .n", image_name);exit(-1);fseek(fp, BLKSIZE+INODESIZE*INODENUM+add0*BLKSIZE, SEEK_SET); for(i=0; (i<len)&&(tempi!='0')&&(i < 512); i+)fputc(tempi, fp);if(i = 512)add1 = inode_arraynum.address1;fseek(fp, BLKSIZE+INODESIZE*INODENUM+add1*BLKSIZE, SEEK_SET);for(; (i < len) && (tempi != '0'); i+)fputc(tempi, fp);fputc('0', fp);fclose(fp);/ 功能: 释放文件块号为 num 的文件占用的空间 void release_blk(int num)FILE *fp;if(fp=fopen(image_name, "r+b") = NULL)printf("Can't open n", image_name); exit(-1);bitmapnum = '0'fseek(fp, num, SEEK_SET);fputc('0', fp);fclose(fp);/ 功能 : 显示帮助命令void help(void)printf("command: nhelp- show help menu nclear - clear the screen ncd- change directory nmkdir- make directory ncreate- create a new file nopen- open a exist file nread - read a file nwrite - write something to a file nclose - close a file ndelet -delete a exist directory nformat - format a exist nlogout - exit user nquit - exit this systemn");/设置文件路径void pathset()char path50;int m,n;if(inode_arrayinum_cur.inum = 0) strcpy(path,user.user_name);elsestrcpy(path,user.user_name); m=0;n=inum_cur;while(m != inum_cur)while(inode_arrayn.iparent != m)n = inode_arrayn.iparent;strcat(path,"/");strcat(path,inode_arrayn.);m = n;n = inum_cur; printf("%s$",path);/功能:切换目录(cd .或者cd dirl)void cd(void)int i;if(argc != 2)printf("Command cd must have two args. n");return ;if(!strcmp(argv1, ".")inum_cur = inode_arrayinum_cur.iparent;elsefor(i = 0; i < INODENUM; i+)if(inode_arrayi.inum>0)&&(inode_arrayi.type='d')&&(inode_arrayi.iparent=inum_cur)&&!strcmp(inode_arrayi.1)&&!strcmp(inode_arrayi.user_name,user.user_name) break;if(i = INODENUM)printf("This directory isn't exsited.n");elseinum_cur = i;/ 功能: 显示当前目录下的子目录和文件 (dir)void dir(void)int i;int dcount=0,fcount=0;short bcount=0;if(argc != 1)printf("Command dir must have one args. n"); return ;/ 遍历 i 节点数组 , 显示当前目录下的子目录和文件名 for(i = 0; i < INODENUM; i+)if(inode_arrayi.inum> 0) &&(inode_arrayi.iparent = inum_cur)&& !strcmp(inode_arrayi.user_name,user.user_name)if(inode_arrayi.type = 'd') dcount+;printf("%-20s<DIR>n", inode_arrayi.);elsefcount+;bcount+=inode_arrayi.length;printf("%-20s%12d bytesn", inode_arrayi.i.length);printf("n printf("%d dir(s) %11d bytesFreeSpacen",dcount,1024*1024-bcount);/ 功能: 在当前目录下创建子目录