收藏 分销(赏)

+模拟UNIX文件系统的设计及实现.doc

上传人:丰**** 文档编号:4316679 上传时间:2024-09-05 格式:DOC 页数:36 大小:521.01KB 下载积分:12 金币
下载 相关 举报
+模拟UNIX文件系统的设计及实现.doc_第1页
第1页 / 共36页
+模拟UNIX文件系统的设计及实现.doc_第2页
第2页 / 共36页


点击查看更多>>
资源描述
******************* 实践教学 ******************* 兰州理工大学 计算机与通信学院 2008年秋季学期 操作系统原理课程设计 题 目: 模拟UNIX文件系统 专业班级: 计算机一班 姓 名: 张树伟 学 号: 06240121 指导教师: 刘嘉 成 绩: 目    录 1. 摘要 2 2. 问题描述 2 3. 设计目的 2 4. 设计要求 2 5. 详细设计 2 5.1界面设计 3 5.1算法设计. 3 6. 设计总结 3 7. 参考文献 4 8. 致谢 4 9. 附录 22 模拟UNIX文件系统的设计及实现 1. 课程设计内容 多用户的多级目录的文件系统设计。 2. 概述 UNIX采用树型目录结构,每个目录表称为一个目录文件。 一个目录文件是由目录项组成的。每个目录项包含16B,一个辅存磁盘块(512B)包含32个目录项。在目录项中,第1、2字节为相应文件的外存i节点号,是该文件的内部标识;后14B为文件名,是该文件的外部标识。所以,文件目录项记录了文件内、外部标识的对照关系。根据文件名可以找到辅存i节点号,由此便得到该文件的所有者、存取权、文件数据的地址健在等信息。UNIX的存储介质以512B为单位划分为块,从0开始直到最大容量并顺序加以编号就成了一个文件卷,也叫文件系统。UNIX中的文件系统磁盘存储区分配图如下: 0# 1# 2# … K# K+1# K+2# K+3# … n# i节点区 文件存储区 引导区 管理区 本次课程设计是要实现一个简单的模拟UNIX文件系统。我们在内存中开辟一个虚拟磁盘空间(1MB)作为文件存储器,并将该虚拟文件系统保存到磁盘上(以一个文件的形式),以便下次可以再将它恢复到内存的虚拟磁盘空间中。文件存储空间的管理可采用位示图方法。 3. 课程设计任务及要求 3.1. 设计任务 多用户、多级目录结构文件系统的设计与实现。可以实现下列几条命令 login 用户登录 logout 退出当前用户 dir 列文件目录 creat 创建文件 delete 删除文件 open 打开文件 close 关闭文件 read 读文件 write 写文件 mkdir 创建目录 ch 改变文件目录 rd 删除目录树 format 格式化文件系统 quit 退出文件系统 3.2. 设计要求 1) 多用户 :usr1,usr2,usr3,……,usr8 (1-8个用户)   2) 多级目录:可有多级子目录; 3) 具有login (用户登录)              4) 系统初始化(建文件卷、提供登录模块) 5) 文件的创建:create (用命令行来实现)       6) 文件的打开:open 7) 文件的读:read                 8) 文件的写:write 9) 文件关闭:close                10) 删除文件:delete 11) 创建目录(建立子目录):mkdir         12) 改变当前目录:cd 13) 列出文件目录:dir              14) 退出:logout 新增加的功能: 15) 删除目录树:rd 16) 格式化文件系统:format 4. 算法及数据结构 4.1. 算法的总体思想 本课程设计是要求我们模拟UNIX文件系统功能设计一个虚拟文件系统,依据UNIX文件系统的特点,其设计思想是: 申请1M的内存空间来虚拟文件系统,将其以512B每块划分2048块,采用位示图管理文件系统的方法,利用其原理将第1块作为位图区(512B),共有对i节点区和数据块区分别建立位图;每个i节点占16B,每块有512/16=32个i节点,用2、3共两块作为i节点,总共有64个i节点,在位图区占用8B;其余2045块作为数据区(本课设要求只用到512块),在位图区占用接近256B(2045位)。 文件系统存储区分配图如下: 位图区 i节点区 数据区 位图:用0表示未使用,1表示使用; i节点:文件控制块(FCB),描述文件信息的一个数据结构; 数据区:存放用户数据,包括目录文件。 位示图用以反映整个存储空间的分配情况,由若干字节构成,每个字节中的每一位对应文件存储器中的一块,“1”状态表示相应块已占用,“0”状态表示该块为空闲。存储块分配时,只要把找到的空闲块所对应的位由 "0" 改为 "1", 而在释放时,只要把被释放的物理块所对应的位由 "1" 改为 " 0 " 即可。分配和释放都可以在内存的位示 图上完成,而且速度较快。磁盘 i 节点利用在内存中生成链表或者数组的方法来生成,并且限制磁盘节点数的最大值。同样内存 i 节点利用链表的方法在内存中生成。同时在往文件中 写或者读的时候我们都是对内存中有内容进行读写。 在该文件系统中,规定一个文件最多只能占用2个数据块,这两个数据块可以是不连续的,其块号记录在一个索引块中,该索引块称为inode结构。 读入一个文件时,先根据目录找到相应的i节点号,将i节点读入主存i节点,建立打开文件表指向该主存i节点,再将文件内容读入主存数据区。 4.2. 系统总体框架图 4.3. 系统总体流程图 开始 文件系统是否建立? 在内存中申请1M内存空间 将磁盘上的文件系统读入内存 Y N 用户登录模块,输入用户名和密码,可以 在程序中设定,不用保存在文件系统中 用户名、密码对吗? 执行init(),进行初始化 操作,进入用户子目录 执行command(),对用户输入的命令进行解析和 执行。若数据被修改或新建立,则保存主存i节 点和数据块的内容到内存的文件系统,并写回磁 盘,保存修改。若输入错误命令则显示出错信息。 退出用户(logout)吗? 用户输入quit吗? 结束 执行format(), 建立文件系统 N N N Y Y Y 4.4. 各模块功能说明 4.4.1 format模块 功能: 格式化文件系统,即初始化文件系统,相当于硬盘的格式化。将其中原有的用户及用户下的文件系统全部还原初始状态,即没有任何用户和目录、文件,也就是按设计的文件系统格式重建新的文件系统。 4.4.2 get_blknum和release_blk模块 功能: 实现i节点的分配和回收; 算法:当一个新的文件被建立时,在给该文件分配磁盘存储区之前,应为该文件分配存放该文件的说明信息的磁盘i节点。反之,当从文件系统中删除某个文件时,则要首先删除它的i节点项。 4.4.3 init()模块 功能: 进入文件系统 算法:初始化用户打开文件系表。在内存中申请一个虚拟存储空间,此空间必须大于或等于可格式化时的空间。将文件系统文件读入虚拟磁盘。 4.4.4 quit()模块 功能:退出文件系统函数quit() 算法:将虚拟磁盘内容保存到磁盘上。释放虚拟磁盘所占据的空间。撤消用用户打开文件表。 4.4.5 Creat()模块 功能: 创建文件 用法:creat filename 算法:分配一空目录项,分配磁盘块。可用位示图。填写该空目录项。如文件长度(0),文件名,类型等。分配一个用户打开文件表项,并填写相关目录,读写指针=0。 4.4.6 open()模块 功能: 打开文件open() 用法:open filename 算法:if(该文件已打开or该文件不存在)报错(出错信息)。分配一个用户打开文件表项。 4.4.7 close()模块 功能: 关闭文件close() 用法:close filename 算法:释放该文件的用户占据的内存空间。清空该文件的用户打开文件表目。 4.4.8 write()模块 功能: 写文件write(fd,buf,len) 用法:write filename,需要先打开文件。 算法:指定写入内容长度。buf。修改打开文件表读/写指针。修改目录项中的文件长度。 4.4.9 read()模块 功能:read(fd,buf,len) 用法:read filename,需先打开文件。 算法:文件信息.修改读/写指针。 4.4.10 delete()模块 功能: 删除文件delete() 用法:delete filename 算法:若文件不存在,报错。回收磁盘空间。回收目录项。 4.5. 该文件系统的数据结构和申明函数 // 用户(20B) typedef struct { char user_name[10]; // 用户名 char password[10]; // 密码 } User; // i节点(32B) typedef struct { short inum; // 文件i节点号 char file_name[10]; // 文件名 char type; // 文件类型 char user_name[10]; // 文件所有者 short iparent; // 父目录的i节点号 short length; // 文件长度 short address[2]; // 存放文件的地址 } Inode; // 打开文件表(16B) typedef struct { short inum; // i节点号 char file_name[10]; // 文件名 short mode; // 读写模式(1:read, 2:write, 3:read and write) short offset; // 偏移量 } File_table; // 申明函数 void login(void); 用户登录,如果是新用户则创建用户 void init(void); 程序初始化,将所有i节点读入内存 int analyse(char *); 输入参数分析,分析用户命令 void save_inode(int); 将num号i节点保存到虚拟磁盘文件hd.dat int get_blknum(void); 申请一个数据块 void read_blk(int); 将i节点号为num的文件读入temp void write_blk(int); 将temp的内容写入hd.dat的数据区 void release_blk(int); 释放文件块号为num的文件占用的空间 void pathset(); 打印当前路径 void deltree(int innum); 实现删除目录树函数 int check(int); 检查用户权限 // 用户命令处理函数 void help(void); 命令提示帮助函数 void cd(void); 改变当前目录 void dir(void); 显示当前目录下所有文件和目录 void mkdir(void); 创建目录 void rd(void); 删除目录 void creat(void); 创建文件 void open(void); 打开 void read(void); 读文件 void write(void); 写文件 void close(void); 关闭文件 void del(void); 删除文件 void logout(void); 用户注销 void command(void); 命令管理函数 void format(void); 格式化虚拟磁盘 5. 程序设计与实现 5.1. 主要函数列表 函数原型 功能 入口、出口参数说明 void login(void) 用户登陆 void init(void)) 程序初始化 int analyse(char *) 输入参数分析 命令行字符串 void save_inode(int) 保存i节点到虚拟磁盘文件 i节点号 int get_blknum(void) 分配一个磁盘块 void read_blk(int) 读磁盘快内容 i节点号 void write_blk(int) 写磁盘块 i节点号 void release_blk(int) 释放一个磁盘块 i节点号 void pathset(); 打印当前路径 void deltree(int innum); 实现删除目录树函数 i节点号 int check(int); 检查用户权限 i节点号 void help(void) 命令提示帮助函数 void dir(void) 显示当前目录下所有文件和目录 void mkdir(void) 创建目录 void creat(void) 创建文件 void open(void) 打开文件 void read(void) 读文件 void write(void) 写文件 void close(void) 关闭文件 void del(void) 删除文件 void logout(void) 用户登出 void command(void) 命令管理函数 void rd(void) 删除目录 void format(void); 格式化虚拟磁盘 5.2. 函数之间的关系 main() login() init() command() analyse() help() cd() dir() mkdir() creat() open() read() write() close() del() logout() cls() errcmd() format() quit() rd() save_inode() read_blk() get_blknum() write_blk() release_blk() delet() 5.3. 程序流程图 各功能模块流程图 是 否 否 是 提示输入用户名和密码 用户名是否存在 创建新用户 读入用户信息到内存 开始 密码是否正确 结束 用户登陆login() 读入位示图信息到内存 读入i节点信息到内存 当前目录为根目录 初始化打开文件表 结束 开始 初始化函数init() 是 是 否 否 遍历i节点区 argv[1]=”..” 目录是否存在 找到的目录i节点号送当前目录inum_cur 当前目录的父i节点号送当前目录inum_cur 开始 结束 改变当前目录cd() 是 是 否 否 遍历i节点区 i节点的父节点是否为当前目录 i节点区是否遍历完 输出文件名或目录名 开始 结束 显示目录dir() 是 是 否 否 遍历i节点区 要创建的目录是否存在 是否有空的i节点 遍历i节点区 分配一个目录i节点 开始 结束 创建目录mkdir() 是 是 否 否 遍历i节点区 要创建的文件是否存在 是否有空的i节点 遍历i节点区 分配一个文件i节点 开始 结束 创建文件creat() 是 否 是 否 是 否 遍历i节点区 要打开的文件是否存在 提示输入打开模式 将打开文件信息写入打开文件信息表file_array[] 遍历打开文件表file_array[] 文件是否已经打开 提示输入开始位置和读字节数 调用读块操作,读出块内字符 模式是否为可读 开始 结束 开始 结束 打开文件open() 读文件read() 是 否 是 否 遍历打开文件表file_array[] 文件是否已经打开 提示输入写入字节数 调用写块操作,写入块内字符 模式是否为可写 是 否 遍历打开文件表file_array[] 文件是否已经打开 将打开文件表项标志位置-1 file_array[i].inum = -1 开始 结束 写文件write() 开始 结束 关闭文件close() 是 否 遍历i节点区 要删除的文件是否存在 释放文件对应的i节点区inode_array[i].inum = -1 释放两个磁盘块 文件是否大于的一块 释放一个磁盘块 是 否 开始 结束 删除文件del() 开始 遍历i节点区 是待删除目录吗? 遍历子目录 子目录为空吗? 是文件吗? 是空目录吗? 结束 调用delet()删 除目录或文件 是空目录吗? 删除目录树rd() 是 是 否 否 否 否 否 是 是 是 是 否 遍历位示图表查找空闲块bitmap[] 是否有空闲块 分配一块,将位示图位置置’1’。 bitmap[i] = '1' 返回找到的空闲块号 将位示图位置置’0’。 bitmap[i] = '0' 清空块内容 开始 结束 分配磁盘块get_blk() 开始 结束 释放磁盘块release_blk(int) 是 否 输出给定i节点对应的第1块内容 文件是否大于1块 输出给定i节点对应的第2块内容 是 否 将缓冲区buf内容写入第1块 buf内容是否大于512字节 将缓冲区buf的512字节后面的内容写入第2块 开始 结束 写磁盘块write_blk(int) 开始 结束 读磁盘块read_blk(int) 5.4. 源程序 第35页 总36页 /*main.c*/ #include "head.h" char choice; int argc; // 用户命令的参数个数 char *argv[5]; // 用户命令的参数 int inum_cur; // 当前目录 char temp[2*BLKSIZE]; // 缓冲区 User user; // 当前的用户 char bitmap[BLKNUM]; // 位图数组 Inode inode_array[INODENUM]; // i节点数组 File_table file_array[FILENUM]; // 打开文件表数组 char image_name[10] = "hd.dat"; // 文件系统名称 FILE *fp; // 打开文件指针 //创建映像hd,并将所有用户和文件清除 void format(void) { FILE *fp; int i; Inode inode; printf("Will be to format filesystem...\n"); printf("WARNING:ALL DATA ON THIS FILESYSTEM WILL BE LOST!\n"); printf("Proceed with Format(Y/N)?"); scanf("%c", &choice); gets(temp); if((choice == 'y') || (choice == 'Y')) { if((fp=fopen(image_name, "w+b")) == NULL) { printf("Can't create file %s\n", image_name); exit(-1); } for(i = 0; i < BLKSIZE; i++) fputc('0', fp); inode.inum = 0; strcpy(inode.file_name, "/"); inode.type = 'd'; strcpy(inode.user_name, "all"); inode.iparent = 0; inode.length = 0; inode.address[0] = -1; inode.address[1] = -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.txt if((fp=fopen("user.txt", "w+")) == NULL) { printf("Can't create file %s\n", "user.txt"); exit(-1); } fclose(fp); printf("Filesystem created successful.Please first login!\n"); } return ; } // 功能: 用户登陆,如果是新用户则创建用户 void login(void) { char *p; int flag; char user_name[10]; char password[10]; char file_name[10] = "user.txt"; do { printf("login:"); gets(user_name); printf("password:"); p=password; while(*p=getch()) { if(*p == 0x0d) //当输入回车键时,0x0d为回车键的ASCII码 { *p='\0'; //将输入的回车键转换成空格 break; } printf("*"); //将输入的密码以"*"号显示 p++; } flag = 0; if((fp = fopen(file_name, "r+")) == NULL) { printf("\nCan't open file %s.\n", file_name); printf("This filesystem 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 file %s.\n", image_name); exit(-1); } // 读入位图 for(i = 0; i < BLKNUM; i++) bitmap[i] = fgetc(fp); // 显示位图 // 读入i节点信息 for(i = 0; i < INODENUM; i++) fread(&inode_array[i], sizeof(Inode), 1, fp); // 显示i节点 // 当前目录为根目录 inum_cur = 0; // 初始化打开文件表 for(i = 0; i < FILENUM; i++) file_array[i].inum = -1; } // 功能: 分析用户命令, 将分析结果填充argc和argv // 结果: 0-14为系统命令, 15为命令错误 int analyse(char *str) { int i; char temp[20]; char *ptr_char; char *syscmd[]={"help", "cd", "dir", "mkdir", "creat", "open", "read", "write", "close", "delete", "logout", "clear","format","quit","rd"}; argc = 0; for(i = 0, ptr_char = str; *ptr_char != '\0'; ptr_char++) { if(*ptr_char != ' ') { while(*ptr_char != ' ' && (*ptr_char != '\0')) temp[i++] = *ptr_char++; argv[argc] = (char *)malloc(i+1); strncpy(argv[argc], temp, i); argv[argc][i] = '\0'; argc++; i = 0; if(*ptr_char == '\0') break; } } if(argc != 0) { for(i = 0; (i < 15) && strcmp(argv[0], syscmd[i]); i++); return i; } else return 15; } // 功能: 将num号i节点保存到hd.dat void save_inode(int num) { if((fp=fopen(image_name, "r+b")) == NULL) { printf("Can't open file %s\n", image_name); exit(-1); } fseek(fp, 512+num*sizeof(Inode), SEEK_SET); fwrite(&inode_array[num], sizeof(Inode), 1, fp); fclose(fp); } // 功能: 申请一个数据块 int get_blknum(void) { int i; for(i = 0; i < BLKNUM; i++) if(bitmap[i] == '0') break; // 未找到空闲数据块 if(i == BLKNUM) { printf("Data area is full.\n"); exit(-1); } bitmap[i] = '1'; if((fp=fopen(image_name, "r+b")) == NULL) { printf("Can't open file %s\n", image_name); exit(-1); } fseek(fp, i, SEEK_SET); fputc('1', fp); fclose(fp); return i; } // 功能: 将i节点号为num的文件读入temp void read_blk(int num) { int i, len; char ch; int add0, add1; len = inode_array[num].length; add0 = inode_array[num].address[0]; if(len > 512) add1 = inode_array[num].address[1]; if((fp = fopen(image_name, "r+b")) == NULL) { printf("Can't open file %s.\n", image_name); exit(-1); } fseek(fp, 1536+add0*BLKSIZE, SEEK_SET); ch = fgetc(fp); for(i=0; (i < len) && (ch != '\0') && (i < 512); i++) { temp[i] = ch; ch = fgetc(fp); } if(i >= 512) { fseek(fp, 1536+add1*BLKSIZE, SEEK_SET); ch = fgetc(fp); for(; (i < len) && (ch != '\0'); i++) { temp[i] = ch; ch = fgetc(fp); } } temp[i] = '\0'; fclose(fp); } // 功能: 将temp的内容输入hd的数据区 void write_blk(int num) { int i, len; int add0, add1; add0 = inode_array[num].address[0]; len = inode_array[num].length; if((fp = fopen(image_name, "r+b")) == NULL) { printf("Can't open file %s.\n", image_name); exit(-1); } fseek(fp, 1536+add0*BLKSIZE, SEEK_SET); for(i=0; (i<len)&&(temp[i]!='\0')&&(i < 512); i++) fputc(temp[i], fp); if(i == 512) { add1 = inode_array[num].address[1]; fseek(fp, 1536+add1*BLKSIZE, SEEK_SET); for(; (i < len) && (temp[i] != '\0'); i++) fputc(temp[i], 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 file %s\n", image_name); exit(-1); } bitmap[num] = '0'; fseek(fp, num, SEEK_SET); fputc('0', fp); fclose(fp); } // 功能: 显示帮助命令 void help(void) { printf("command: \n\ help --- show help menu \n\ clear --- clear the screen \n\ cd --- change directory \n\ mkdir --- make directory \n\ creat --- create a new file \n\ open --- open a exist file \n\ read --- read a file \n\ write --- write something to a file \n\ close --- close a file \n\ delete --- delete a exist file \n\ format --- format a exist filesystem \n\ logout --- exit user \n\ rd --- delete a directory \n\ quit --- exit this system\n"); } //设置文件路径 void pathset() { char path[50]; int m,n; if(inode_array[inum_cur].inum == 0) strcpy(path,user.user_name); else { strcpy(path,user.user_name); m=0; n=inum_cur; while(m != inum_cur) { while(inode_array[n].iparent != m) { n = inode_array[n].iparent; } strcat(path,"/"); strcat(path,inode_array[n].file_name); m = n; n = inum_cur; } } printf("[%s]@",path); } // 功能: 切换目录(cd
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服