




已阅读5页,还剩11页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
杭州电子科技大学操作系统课程设计课程设计题目:简单文件系统的实现姓名:徐凯辉班级: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块引导块FAT1 FAT2 数据区格式化时,主要包括引导块,FAT1,FAT2,的一些初始化工作例如设置文件魔数,文件系统的信息,FAT1,FAT2的信息等等iii. 根据用户输入的命令,调用对应的函数.2. 程序流程图程序启动加载文件系统文件系统存在创建新的文件系统并格式化文件系统不存在等待用户输入命令CreateMkdirlsExit。四, 系统关键数据结构(1)文件控制块FCB 用于记录文件的描述和控制信息,每个文件设置一个FCB,它也是文件的目录项的内容。 typedef struct FCB /仿照FAT16设置的 char filename8; /文件名char exname3;/文件扩展名unsigned char attribute;/文件属性字段:为简单起见,我们只为文件设置了两种属性:/值为0时表示目录文件,值为1时表示数据文件unsigned short time;/文件创建时间unsigned short data;/文件创建日期unsigned short first;/文件起始盘块号unsigned long length;/文件长度(字节数) char free;/表示目录项是否为空,若值为0,表示空,值为1,表示已分配fcb; (2)文件分配表FAT typedef struct FATunsigned short id;fat;(3)用户打开文件表USEROPEN当打开一个文件时,必须将文件的目录项中的所有内容全部复制到内存中,同时还要记录有关文件操作的动态信息,如读写指针的值等。在本实例中实现的是一个用于单用户单任务系统的文件系统,为简单起见,我们把用户文件描述符表和内存FCB表合在一起,称为用户打开文件表,表项数目为10,即一个用户最多可同时打开10个文件。然后用一个数组来描述,则数组下标即某个打开文件的描述符。另外,我们在用户打开文件表中还设置了一个字段“char dir80”,用来记录每个打开文件所在的目录名,以方便用户打开不同目录下具有相同文件名的不同文件。typedef struct USEROPENchar filename8; /文件名char exname3;/文件扩展名unsigned char attribute;/文件属性:值为0时表示目录文件,值为1时表示数据文件unsigned short time;/文件创建时间unsigned short data;/文件创建日期unsigned short first;/文件起始盘块号unsigned long length;/文件长度(对数据文件是字节数,对目录文件可以是目录项个数)char free;/表示目录项是否为空,若值为0,表示空,值为1,表示已分配 /前面内容是文件的FCB中的内容。 / 下面设置的dirno和diroff记录了相应打开文件的目录项在父目录文件中的位置,/这样如果该文件的fcb被修改了,则要写回父目录文件时比较方便int dirno; /相应打开文件的目录项在父目录文件中的盘块号 int diroff;/ 相应打开文件的目录项在父目录文件的dirno盘块中的目录项序号 char dirMAXOPENFILE80; /相应打开文件所在的目录名,这样方便快速检查出/指定文件是否已经打开int count; /读写指针在文件中的位置 char fcbstate; /是否修改了文件的FCB的内容,如果修改了置为1,否则为0char topenfile; /表示该用户打开表项是否为空,若值为0,表示为空,否则表示已/被某打开文件占据useropen;(4)引导块BLOCK0在引导块中主要存放逻辑磁盘的相关描述信息,比如磁盘块大小、磁盘块数量、文件分配表、根目录区、数据区在磁盘上的起始位置等。如果是引导盘,还要存放操作系统的引导信息。本实例是在内存的虚拟磁盘中创建一个文件系统,因此所包含的内容比较少,只有磁盘块大小、磁盘块数量、数据区开始位置、根目录文件开始位置等。typedef struct BLOCK0 /引导块内容/存储一些描述信息,如磁盘块大小、磁盘块数量、最多打开文件数等、char information200; unsigned short root; /根目录文件的起始盘块号unsigned char *startblock; /虚拟磁盘上数据区开始位置block0;4全局变量定义(1)unsigned char *myvhard: 指向虚拟磁盘的起始地址 (2)useropen openfilelistMAXOPENFILE: 用户打开文件表数组(3)useropen *ptrcurdir: 指向用户打开文件表中的当前目录所在打开文件表项的位置;(4)char currentdir80: 记录当前目录的目录名(包括目录的路径)(5)unsigned char* startp: 记录虚拟磁盘上数据区开始位置5虚拟磁盘空间布局由于真正的磁盘操作需要涉及到设备的驱动程序,所以本实例是在内存中申请一块空间作为虚拟磁盘使用,我们的文件系统就建立在这个虚拟磁盘上。虚拟磁盘一共划分成1000个磁盘块,每个块1024个字节,其布局格式是模仿FAT文件系统设计的,其中引导块占一个盘块,两张FAT各占2个盘块,剩下的空间全部是数据区,在对虚拟磁盘进行格式化的时候,将把数据区第1块(即虚拟磁盘的第6块)分配给根目录文件,如图3-3所示:图3-3 虚拟磁盘空间布局五, 系统详细设计、1, 格式化磁盘/ 磁盘格式化函数void my_format() block0 *b0; unsigned char *p; fat *fat1, *fat2; int i; fcb *root, *root0; time_t rawtime; struct tm *timeinfo; FILE *fp; printf(Start format filesystem .n); / 将虚拟磁盘第一个块作为引导块 b0 = (block0 *)myvhard; / 文件系统的魔数 memcpy(b0-magic_number, 10101010, 8); / 文件系统的描述信息 strcpy(b0-infomation, My FileSystem V1.0n); 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; i 5; i+) / 前 5 个块是设置为已分配 fat1i.id = END; fat2i.id = END; for (; i filename, .); / 根目录文件名 strcpy(root-exname, di); / 根目录文件拓展名 root-attribute = 0; rawtime = time(NULL); / 获取时间,以秒计,从1970年1月1日起算,存于rawtime timeinfo = 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 filename, ); root0+; / 写入文件 fp = fopen(filename , w); fwrite(myvhard, SIZE, 1, fp); fclose(fp); update_openfilelist0(); printf(Format filesystem ok.n);2, 创建目录a) 调用do_read读入当前目录文件到内存,检查新建文件目录是否重名b) 分配一个空闲的打开文件表项c) 分配一个空闲的盘块d) 在当前目录中问新建目录寻找一个空闲的目录项e) 设置FCB,文件的属性信息f) 创建特殊的两个目录项.,.g) 返回 / 创建子目录void my_mkdir(char *dirname) int filelen; fcb *fcbptr, fcbtmp, fcbtmp0; char textMAX_TEXT_SZIE, *p; int i, fd; unsigned short numOfBlock; unsigned char *blockptr; time_t rawtime; struct tm *timeinfo; fat *fat1; fat1 = (fat *)(myvhard + BLOCKSIZE); / 调用do_read()读入当前目录文件内容到内存 openfilelistcurrfd.count = 0; filelen = do_read(currfd, (int)openfilelistcurrfd.length, text); fcbptr = (fcb *)text; / 检查当前目录下新建目录文件是否重名 for (i = 0; i filename) = 0) printf(Error : the dirname is already exist.n); return ; fcbptr+; / 为新建子目录文件分配一个空闲打开文件表项 fd = getFreeOpenfilelist(); printf(Find free openfilelist : %dn, fd); if (fd 0) return; / 为新目录文件分配一个盘块 numOfBlock = getFreeBLOCK(); printf(Find free block : %dn, numOfBlock); if (numOfBlock 0) my_close(fd); return; fat1numOfBlock.id = END; fcbptr = (fcb *)text; / 在当前目录中为新建目录文件寻找一个空闲的目录项或为其追加一个新的目录项 for (i = 0; i filename, ) = 0) break; fcbptr+; openfilelistcurrfd.count = i * sizeof(fcb); openfilelistcurrfd.fcbstate = 1; / 在当前目录新建目录项 strcpy(fcbtmp.filename, dirname); strcpy(fcbtmp.exname, di); fcbtmp.attribute = 0; rawtime = time(NULL); / 获取时间,以秒计,从1970年1月1日起算,存于rawtime timeinfo = localtime(&rawtime); / 转为当地时间 fcbtmp.time = timeinfo-tm_hour * 2048 + timeinfo-tm_min * 32 + timeinfo-tm_sec / 2; / 文件创建时间 fcbtmp.date = (timeinfo-tm_year - 80) * 512 + (timeinfo-tm_mon + 1) * 32 + timeinfo-tm_mday; / 文件创建创建日期 fcbtmp.first = numOfBlock; fcbtmp.length = 2 * sizeof(fcb); fcbtmp.free = 1; do_write(currfd, (char *)(&fcbtmp), sizeof(fcb), 2); openfilelistcurrfd.length += sizeof(fcb); / 设置新建目录项的打开文件表项 strcpy(openfilelistfd.filename, fcbtmp.filename); strcpy(openfilelistfd.exname, fcbtmp.exname); openfilelistfd.attribute = fcbtmp.attribute; openfilelistfd.time = fcbtmp.time; openfilelistfd.date = fcbtmp.date; openfilelistfd.first = fcbtmp.first; openfilelistfd.length = fcbtmp.length; openfilelistfd.free = fcbtmp.free; openfilelistfd.dirno = openfilelistcurrfd.first; openfilelistfd.diroff = i; strcpy(openfilelistfd.dirfd, openfilelistcurrfd.dircurrfd); p = openfilelistfd.dirfd; while (*p != 0) p+; strcpy(p, dirname); while (*p != 0) p+; *p = /; p+; *p = 0; openfilelistfd.count = 0; openfilelistfd.fcbstate = 0; openfilelistfd.topenfile = 1; / 在新建目录文件所分配到的磁盘块中建立“.“和“.” blockptr = (unsigned char *)(myvhard + numOfBlock * BLOCKSIZE); fcbptr = (fcb *)blockptr; / 创建目录项 . strcpy(fcbtmp.filename, .); / 根目录文件名 strcpy(fcbtmp.exname, di); / 根目录文件拓展名 fcbtmp.attribute = 0; rawtime = time(NULL); / 获取时间,以秒计,从1970年1月1日起算,存于rawtime timeinfo = localtime(&rawtime); / 转为当地时间 fcbtmp.time = timeinfo-tm_hour * 2048 + timeinfo-tm_min * 32 + timeinfo-tm_sec / 2; / 文件创建时间 fcbtmp.date = (timeinfo-tm_year - 80) * 512 + (timeinfo-tm_mon + 1) * 32 + timeinfo-tm_mday; / 文件创建创建日期 fcbtmp.first = numOfBlock; / 文件起始盘块号 fcbtmp.length = 2 * sizeof(fcb); fcbtmp.free = 1; / 复制目录项 . 为 . memcpy(&fcbtmp0, &fcbtmp, sizeof(fcb); strcpy(fcbtmp0.filename, .); fcbtmp0.first = openfilelistcurrfd.first; fcbtmp0.length = openfilelistcurrfd.length; do_write(fd, (char *)(&fcbtmp), sizeof(fcb), 2); do_write(fd, (char *)(&fcbtmp0), sizeof(fcb), 2); / 更新当前目录文件的长度 openfilelistcurrfd.count = 0; do_read(currfd, (int)openfilelistcurrfd.length, text); fcbptr = (fcb *)text; fcbptr-length = openfilelistcurrfd.length; openfilelistcurrfd.count = 0; do_write(currfd, text, (int)fcbptr-length, 2); my_close(fd);3, Cd命令a) Open指定的目录名,调用read读入该父目录到内存b) 检查新的当前目录名是否存在c) 关闭原当前目录d) 设置当前目录为该目录4, Rmdir命令a) Read读入当前目录文件内容到内存,检查要删除的文件目录是否存在b) 检查该目录是否为空c) 检查是否已经打开,打开用close则关闭d) 回收给目录文件的磁盘块e) 修改该目录文件的目录项f) 修改用户打开表项的长度信息g) 返回5, Ls命令a) Read当前目录到内存b) 读出目录文件的信息,显示到屏幕上c) 返回6, Create命令a) 分配一个空闲的打开文件表项b) 检查新文件的父目录是否打开c) Read该父目录的文件到内存,并检测新建的文件名是否重名d) 检查是否有空闲盘块e) 寻找空闲的目录项f) 准备好新文件的FCBg) 调用close关闭打开的父目录文件h) 返回7, Rm命令a) 检查要删除的文件的父目录是否已打开b) Read父目录到内存c) 检查文件是否打开d) 回收磁盘快e) 清空该文件的目录项f) 修改用户打开文件表项中的长度信息g) 返回8, Open命令a) 检查该文件名是否存在b) Read该父目录到内存c) 检查用户打开的文件表中是否有空闲表项d) 为该文件填写空白用户打开文件表项内容e) 返回/ 打开文件int my_open(char *filename) char *fname, *exname, *p; int i, fd; char textMAX_TEXT_SZIE; fcb *fcbptr; int fcblen; char *direxname = di; fname = strtok(filename, .); exname = strtok(NULL, .); if (exname = NULL) exname = direxname; / 检查该文件是否以及打开 for (i = 0; i MAXOPENFILE; i+) if (strcmp(fname, openfilelisti.filename) = 0 & strcmp(exname, openfilelisti.exname) = 0) printf(Error : The file is already open. The FileHandle is %d.n, i); return -1; / 读出父目录文件到内存 openfilelistcurrfd.count = 0; fcblen = do_read(currfd, (int)openfilelistcurrfd.length, text); fcbptr = (fcb *)text; / 检查该目录下欲打开文件是否存在 for (i = 0; i filename) = 0 & strcmp(exname, fcbptr-exname) = 0) break; fcbptr+; if (i = (int)(fcblen/sizeof(fcb) printf(Error : The file not exist.n); return -1; / 为打开文件分配一个空表项 fd = getFreeOpenfilelist(); if (fd = -1) return -1; / 为该文件填写空白用户打开文件表表项,读写指针置为0 strcpy(openfilelistfd.filename, fcbptr-filename); strcpy(openfilelistfd.exname, fcbptr-exname); openfilelistfd.attribute = fcbptr-attribute; openfilelistfd.time = fcbptr-time; openfilelistfd.date = fcbptr-date; openfilelistfd.first = fcbptr-first; openfilelistfd.length = fcbptr-length; openfilelistfd.free = fcbptr-free; openfilelistfd.dirno = openfilelistcurrfd.first; openfilelistfd.diroff = i; strcpy(openfilelistfd.dirfd, openfilelistcurrfd.dircurrfd); p = openfilelistfd.dirfd; while (*p != 0) p+; strcpy(p, fname); while (*p != 0) p+; if (fcbptr-attribute = 0) *p = /; p+; *p = 0; else *p = .; p+; strcpy(p, fcbptr-exname); openfilelistfd.count = 0; openfilelistfd.fcbstate = 0; openfilelistfd.topenfile = 1; printf(The FileHandle is %d.n, fd); return fd;9, Closea) 检查fd的有效性b) 检查用户打开文件表表项的fcbstate字段c) 回收该文件占据的用户打开文件表表项d) 返回10, Write命令a) 检查fd的有效性b) 提示用户输入写方式c) 提示用户输入内容d) 调用do_write()将键入的内容写入到文件中e) 返回写入的字节数/ 写文件int my_write(int fd) fat *fat1, *fatptr; unsigned char *p; int wstyle, numOfBlock, writelen, temp; char textMAX_TEXT_SZIE; fat1 = (fat *)(myvhard + BLOCKSIZE); / 检查fd的有效性 if(fd MAXOPENFILE) printf(Error : The file is not exist.n); return -1; / 提示并等待用户输入写方式:(1. 截断写, 2. 覆盖写, 3. 追加写) wstyle = 0; while(wstyle 3) printf(Please select write style:n); printf(1. c
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 汉字笔顺规则课件
- 汉字的演变史
- 内蒙古巴彦淖尔市乌拉特前旗第三中学2025届九年级下学期学业水平考试模拟(三模)数学试卷(含答案)
- 广东省肇庆市2024-2025学年高一下学期期末统一考试物理试卷(含解析)
- 2024-2025学年广东省茂名市高州市八年级(下)5月月考数学试卷(含答案)
- 硬件按需购买模式的市场研究
- 传统文化保护传承与现代文化创新融合探讨
- 网约车行业监管政策分析
- 汉字书法课件模板楷书庵
- 汉字书写讲解课件
- 初中地理学科课程规划方案
- 定额〔2025〕1号文-关于发布2018版电力建设工程概预算定额2024年度价格水平调整的通知
- 塑胶模具类中英文对照专业术语
- 安全- 中国移动认证考试L1题库(附答案)
- 干部民主推荐表(样式)
- 【公开课】社区教案
- 平面磨床操作时注意事项
- GB/T 29651-2013锰矿石和锰精矿全铁含量的测定火焰原子吸收光谱法
- GB/T 13275-1991一般用途离心通风机技术条件
- 核心素养下的高考语文命题评价体系讲座课件
- 高一英语必修一试卷(含答案)(适合测试)
评论
0/150
提交评论