2022年操作系统文件管理系统模拟实验 .pdf
文件管理系统模拟1. 实验目的通过一个简单多用户文件系统的设计,加深理解文件系统的内部功能及内部实现2. 实验内容为 Linux 系统设计一个简单的二级文件系统。要求做到以下几点:(1)可以实现下列几条命令(至少4 条)login 用户登录dir 列文件目录create 创建文件delete 删除文件open 打开文件close 关闭文件read 读文件write 写文件(2)列目录时要列出文件名、物理地址、保护码和文件长度;(3)源文件可以进行读写保护。3. 实验提示(1)首先应确定文件系统的数据结构:主目录、子目录及活动文件等。主目录和子目录都以文件的形式存放于磁盘,这样便于查找和修改。(2)用户创建的文件,可以编号存储于磁盘上。入file0,file1,file2并以编号作为物理地址,在目录中进行登记。4. 源代码#include #include #include #define MEM_D_SIZE 1024*1024 / 总磁盘空间为 1M #define DISKSIZE 1024 / 磁盘块的大小 1K #define DISK_NUM 1024 / 磁盘块数目 1K #define FATSIZE DISK_NUM*sizeof(struct fatitem)/FAT 表大小#define ROOT_DISK_NO FATSIZE/DISKSIZE+1 / 根目录起始盘块号#define ROOT_DISK_SIZE sizeof(struct direct) /根目录大小#define DIR_MAXSIZE 1024 / 路径最大长度为 1KB #define MSD 5 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 18 页 - - - - - - - - - / 最大子目录数 5 #define MOFN 5 / 最大文件深度为 5 #define MAX_WRITE 1024*128 / 最大写入文字长度128KB struct fatitem /* size 8*/ int item; /*存放文件下一个磁盘的指针 */ char em_disk; /* 磁盘块是否空闲标志位 0 空闲*/ ; struct direct /*-文件控制快信息 -*/ struct FCB char name9; /*文件/ 目录名 8 位*/ char property; /*属性 1 位目录 0 位普通文件 */ int size; /*文件 / 目录字节数、盘块数 )*/ int firstdisk; /*文件 / 目录 起始盘块号 */ int next; /*子目录起始盘块号*/ int sign; /*1是根目录 0不是根目录 */ directitemMSD+2; ; struct opentable struct openttableitem char name9; /*文件名 */ int firstdisk; /*起始盘块号*/ int size; /*文件的大小 */ openitemMOFN; int cur_size; /*当前打文件的数目*/ ; struct fatitem *fat; /*FAT表*/ struct direct *root; /*根目录 */ struct direct *cur_dir; /*当前目录*/ struct opentable u_opentable; /*文件打开表 */ int fd=-1; /*文件打开表的序号*/ char *bufferdir; /*记录当前路径的名称 */ char *fdisk; /*虚拟磁盘起始地址*/ void initfile(); void format(); void enter(); void halt(); int create(char *name); int open(char *name); int close(char *name); int write(int fd,char *buf,int len); int read(int fd,char *buf); int del(char *name); int mkdir(char *name); int rmdir(char *name); void dir(); int cd(char *name); void print(); void show(); void initfile() fdisk = (char *)malloc(MEM_D_SIZE*sizeof(char); /*申请 1M 空间*/ format(); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 18 页 - - - - - - - - - void format() int i; FILE *fp; fat = (struct fatitem *)(fdisk+DISKSIZE); /*计算 FAT表地址,引导区向后偏移 1k)*/ /*-初始化FAT表-*/ fat0.item=-1; /*引导块 */ fat0.em_disk=1; for(i=1;iROOT_DISK_NO-1;i+) /* 存放 FAT 表的磁盘块号 */ fati.item=i+1; fati.em_disk=1; fatROOT_DISK_NO.item=-1; /* 存放根目录的磁盘块号 */ fatROOT_DISK_NO.em_disk=1; for(i=ROOT_DISK_NO+1;idirectitem0.sign = 1; root-directitem0.firstdisk = ROOT_DISK_NO; strcpy(root-directitem0.name,.); root-directitem0.next = root-directitem0.firstdisk; root-directitem0.property = 1; root-directitem0.size = ROOT_DISK_SIZE; /*-指向上一级目录的目录项-*/ root-directitem1.sign = 1; root-directitem1.firstdisk = ROOT_DISK_NO; strcpy(root-directitem1.name,.); root-directitem1.next = root-directitem0.firstdisk; root-directitem1.property = 1; root-directitem1.size = ROOT_DISK_SIZE; if(fp = fopen(disk.dat,wb)=NULL) printf(Error:n Cannot open file n); return; for(i=2;idirectitemi.sign = 0; root-directitemi.firstdisk = -1; strcpy(root-directitemi.name,); root-directitemi.next = -1; root-directitemi.property = 0; root-directitemi.size = 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 18 页 - - - - - - - - - 0; if(fp = fopen(disk.dat,wb)=NULL) printf(Error:n Cannot open file n); return; if(fwrite(fdisk,MEM_D_SIZE,1,fp)!=1) /*把虚拟磁盘空间保存到磁盘文件中 */ printf(Error:n File write error! n); fclose(fp); void enter() FILE *fp; int i; fdisk = (char *)malloc(MEM_D_SIZE*sizeof(char); /*申请 1M空间*/ if(fp=fopen(disk.dat,rb)=NULL) printf(Error:nCannot open filen); return; if(!fread(fdisk,MEM_D_SIZE,1,fp) /*把磁盘文件disk.dat 读入虚拟磁盘空间 ( 内存)*/ printf(Error:nCannot read filen); exit(0); fat = (struct fatitem *)(fdisk+DISKSIZE); /*找到 FAT表地址*/ root = (struct direct *)(fdisk+DISKSIZE+FATSIZE);/*找到根目录地址 */ fclose(fp); /*-初始化用户打开表-*/ for(i=0;i8) /*文件名大于 8 位*/ return(-1); for(j=2;jdirectitemj.name,name) break; if(jMSD+2) /*文件已经存在*/ return(-4); for(i=2;idirectitemi.firstdisk=-1) break; if(i=MSD+2) /*无空目录项 */ return(-2); if(u_opentable.cur_size=MOFN) /*打开文件太多 */ return(-3); for(j=ROOT_DISK_NO+1;j=DISK_NUM) return(-5); fatj.em_disk = 1; /*将空闲块置为已经分配 */ /*-填 写 目 录 项-*/ strcpy(cur_dir-directitemi.name,name); cur_dir-directitemi.firstdisk = j; cur_dir-directitemi.size = 0; cur_dir-directitemi.next = j; cur_dir-directitemi.property = 0; /*-*/ fd = open(name); return 0; int open(char *name) int i, j; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 18 页 - - - - - - - - - for(i=2;idirectitemi.name,name) break; if(i=MSD+2) return(-1); /*-是 文 件 还 是 目 录-*/ if(cur_dir-directitemi.property=1) return(-4); /*-文 件 是 否 打 开-*/ for(j=0;jMOFN;j+) if(!strcmp(u_opentable.openitemj.name,name) break; if(j=MOFN) /*文件打开太多 */ return(-3); /*-查找一个空闲用户打开表项 -*/ for(j=0;jdirectitemi.firstdisk; strcpy(u_opentable.openitemj.name,name); u_opentable.openitemj.size = cur_dir-directitemi.size; u_opentable.cur_size+; /*-返回用户打开表表项的序号-*/ return(j); int close(char *name) int i; for(i=0;i=MOFN) return(-1); /*-清 空该 文 件 的用户打开表项的内容-*/ strcpy(u_opentable.openitemi.name,); u_opentable.openitemi.firstdisk = -1; u_opentable.openitemi.size = 0; u_opentable.cur_size-; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 18 页 - - - - - - - - - return 0; int write(int fd, char *buf, int len) char *first; int item, i, j, k; int ilen1, ilen2, modlen, temp; /*-用 $ 字符作为空格# 字符作为换行符-*/ char Space = 32; char Endter= n; for(i=0;ilen;i+) if(bufi = $) bufi = Space; else if(bufi = #) bufi = Endter; /*-读取用户打开表对应表项第一个盘块号-*/ item = u_opentable.openitemfd.firstdisk; /*-找到当前目录所对应表项的序号-*/ for(i=2;idirectitemi.firstdisk=item) break; temp = i; /*-存放当前目录项的下标-*/ /*-找到的 item 是该文件的最后一块磁盘块-*/ while(fatitem.item!=-1) item =fatitem.item; /*-查找该文件的下一盘块 -*/ /*-计算出该文件的最末地址-*/ first = fdisk+item*DISKSIZE+u_opentable.openitemfd.size%DISKSIZE; /*-如果最后磁盘块剩余的大小 大 于 要 写 入 的 文 件 的 大 小-*/ if(DISKSIZE-u_opentable.openitemfd.size%DISKSIZElen) strcpy(first,buf); u_opentable.openitemfd.size = u_opentable.openitemfd.size+len; cur_dir-directitemtemp.size = cur_dir-directitemtemp.size+len; else for(i=0;i0) ilen2 = ilen2+1; /*-还需要多少块磁盘块 -*/ for(j=0;jilen2;j+) for(i=ROOT_DISK_NO+1;i=DISK_NUM) /*-如果磁盘块已经分配完了 -*/ return(-1); first = fdisk+i*DISKSIZE; /*-找到的那块空闲磁盘块的起始地址 -*/ if(j=ilen2-1) /*-如果是最后要分配的一块 -*/ for(k=0;klen-(DISKSIZE-u_opentable.openitemfd.size%DISKSIZE)-j*DISKSIZE;k+) firstk = bufk; else/*-如果不是要最后分配的一块 -*/ for(k=0;kdirectitemtemp.size = cur_dir-directitemtemp.size+len; return 0; int read(int fd, char *buf) int len = u_opentable.openitemfd.size; char *first; int i, j, item; int ilen1, modlen; item = u_opentable.openitemfd.firstdisk; ilen1 = len/DISKSIZE; modlen = len%DISKSIZE; if(modlen!=0) ilen1 = ilen1+1; /*-计算名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 18 页 - - - - - - - - - 文件所占磁盘的块数 -*/ first = fdisk+item*DISKSIZE; /*-计算文件的起始位置 -*/ for(i=0;iilen1;i+) if(i=ilen1-1) /*-如果在最后一个磁盘块 -*/ for(j=0;jlen-i*DISKSIZE;j+) bufi*DISKSIZE+j = firstj; else /*-不在最后一块磁盘块-*/ for(j=0;jlen-i*DISKSIZE;j+) bufi*DISKSIZE+j = firstj; item = fatitem.item; /*- 查找下一盘块 -*/ first = fdisk+item*DISKSIZE; return 0; int del(char *name) int i,cur_item,item,temp; for(i=2;idirectitemi.name,name) break; cur_item = i; /*-用来保存目录项的序号 , 供释放目录中 -*/ if(i=MSD+2) /*-如果不在当前目录中 -*/ return(-1); if(cur_dir-directitemcur_item.property!=0) /*-如果删除的( 不) 是目录 -*/ return(-3); for(i=0;idirectitemcur_item.firstdisk;/*-该 文 件 的 起 始 盘 块 号-*/ while(item!=-1) /*-释放空间 ,将 FAT表对应项进行修改 -*/ temp = fatitem.item; fatitem.item = -1; fatitem.em_disk = 0; item = temp; /*-释放目录项-*/ cur_dir-directitemcur_item.sign = 0; cur_dir-directitemcur_item.firstdisk = -1; strcpy(u_opentable.openitemcur_item.name,); cur_dir-directitemcur_item.next = -1; cur_dir-directitemcur_item.pr名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 18 页 - - - - - - - - - operty = 0; cur_dir-directitemcur_item.size = 0; return 0; int mkdir(char *name) int i,j; struct direct *cur_mkdir; if(!strcmp(name,.) return(-4); if(!strcmp(name,.) return(-4); if(strlen(name)8) /*-如果目录名长度大于 8 位-*/ return(-1); for(i=2;idirectitemi.firstdisk=-1) break; if(i=MSD+2) /*-目录 / 文件已满-*/ return(-2); for(j=2;jdirectitemj.name,name) break; if(jMSD+2) /*-如果有重名 -*/ return(-3); for(j=ROOT_DISK_NO+1;j=DISK_NUM) return(-5); fatj.em_disk=1; /*-将该空闲块设置为已分配 -*/ /*-填 写 目 录 项-*/ strcpy(cur_dir-directitemi.name,name); cur_dir-directitemi.firstdisk=j; cur_dir-directitemi.size=ROOT_DISK_SIZE; cur_dir-directitemi.next=j; cur_dir-directitemi.property=1; /*- 所创目录在虚拟磁盘上的地址( 内存物理地址 )-*/ cur_mkdir=(struct direct *)(fdisk+cur_dir-directitemi.firstdisk*DISKSIZE); /*- 初始化目录 -*/ /*- 指向当前目录的目录项 -*/ cur_mkdir-directitem0.sign=0; cur_mkdir-directitem0.firstdisk=cur_dir-directitemi.firstdisk; strcpy(cur_mkdir-directitem0.name,.); cur_mkdir-directitem0.next=cur_mkdir-directitem0.firstdisk; cur_mkdir-directitem0.property=1; cur_mkdir-directitem0.size名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 18 页 - - - - - - - - - =ROOT_DISK_SIZE; /*- 指向上一级目录的目录项 -*/ cur_mkdir-directitem1.sign=cur_dir-directitem0.sign; cur_mkdir-directitem1.firstdisk=cur_dir-directitem0.firstdisk; strcpy(cur_mkdir-directitem1.name,.); cur_mkdir-directitem1.next=cur_mkdir-directitem1.firstdisk; cur_mkdir-directitem1.property=1; cur_mkdir-directitem1.size=ROOT_DISK_SIZE; for(i=2;idirectitemi.sign=0; cur_mkdir-directitemi.firstdisk=-1; strcpy(cur_mkdir-directitemi.name,); cur_mkdir-directitemi.next=-1; cur_mkdir-directitemi.property=0; cur_mkdir-directitemi.size=0; return 0; int rmdir(char *name) int i,j,item; struct direct *temp_dir; /*- 检查当前目录项中有无该目录-*/ for(i=2;idirectitemi.name,name) break; if(i=MSD+2) /*-没有这个文件或目录 -*/ return(-1); if(cur_dir-directitemi.property!=1)/*-删除的不是目录 -*/ return(-3); /*- 判断要删除的目录有无子目录-*/ temp_dir=(struct direct *)(fdisk+cur_dir-directitemi.next*DISKSIZE); for(j=2;jdirectitemj.next!=-1) break; if(jdirectitemi.firstdisk; fatitem.em_disk=0; /*- 修改目录项 -*/ cur_dir-directitemi.sign=0; cur_dir-directitemi.firstdisk=-1; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 18 页 - - - - - - - - - strcpy(cur_dir-directitemi.name,); cur_dir-directitemi.next=-1; cur_dir-directitemi.property=0; cur_dir-directitemi.size=0; return 0; void dir() int i; for(i=2;idirectitemi.firstdisk!=-1) /*-如果存在子目录 -*/ printf(%st,cur_dir-directitemi.name); if(cur_dir-directitemi.property=0) /*-文件-*/ printf(%dttn,cur_dir-directitemi.size); else printf(ttn); int cd(char *name) int i,j,item; char *str; char *temp,*point,*point1; struct direct *temp_dir; temp_dir=cur_dir; str=name; if(!strcmp(,name) cur_dir = root; strcpy(bufferdir,Root:); return 0; temp = (char *)malloc(DIR_MAXSIZE*sizeof(char);/*-最长路径名字分配空间 -*/ for(i=0;i(int)strlen(str);i+) tempi=stri; tempi=0; for(j=0;jdirectitemj.name,temp) break; free(temp);/*释放申请的临时空间*/ /if(temp_dir-directitemj.property!=1) /*-打开的不是目录-*/ /return(-2); if(j=MSD+2) /*-不在当前目录-*/ return(-1); item=temp_dir-directitemj.firstdisk; /*- 当前目录在磁盘中位置 -*/ temp_dir=(struct direct *)(fdisk+item*DISKSIZE); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 18 页 - - - - - - - - - if(!strcmp(.,name) if(cur_dir-directitemj-1.sign!=1) /*-如果上级目录不是根目录-*/ point=strchr(bufferdir,); / 查找字符串bufferdir中首次出现字符 的位置while(point!=NULL) point1=point+1; /*-减去 所占的空间 , 记录下次查找的起始地址 -*/ point=strchr(point1,); *(point1-1)=0; /*-将上一级目录删除 -*/ else /if(name0 !=) bufferdir = strcat(bufferdir,); /*-修改当前目录 -*/ bufferdir = strcat(bufferdir,name); cur_dir=temp_dir; /*- 将 当前目录确定下来 -*/ return 0; void show() printf(%s,bufferdir); void print() printf(*n); printf(*文件系统设计*n); printf(*t命令格式说 明*n); printf(*tcd 目录名更 改当前目录*n); printf(*tmkdir 目录名创建子目录*n); printf(*trmdir 目录名删除子目录*n); printf(*tdir 显 示当前目录的子目录*n); printf(*tcreate 文件名创建文件*n); printf(*tdel 文件名删除文件*n); printf(*topen 文件名打开文件*n); printf(*tclose 文件名关闭文件*n); printf(*tread 读 文件*n); printf(*twrite 写 文件*n); printf(*texit 退 出系统*n); printf(*n); void main() FILE *fp; char ch; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 18 页 - - - - - - - - - char a100; char code1110; char name10; int i,flag,r_size; char *contect; contect = (char *)malloc(MAX_WRITE*sizeof(char); if(fp=fopen(disk.dat,rb)=NULL) printf(You have not format,Do you want format?(y/n); scanf(%c,&ch); if(ch=y) initfile(); printf(Successfully format! n); else return; enter(); print(); show(); strcpy(code0,exit); strcpy(code1,create); strcpy(code2,open); strcpy(code3,close); strcpy(code4,write); strcpy(code5,read); strcpy(code6,del); strcpy(code7,mkdir); strcpy(code8,rmdir); strcpy(code9,dir); strcpy(code10,cd); while(1) scanf(%s,a); for(i=0;i11;i+) if(!strcmp(codei,a) break; switch(i) case 0: /退出文件系统free(contect); halt(); return; case 1: /创建文件scanf(%s,name); flag = create(name); if(flag=-1) printf(Error: n The length is too long !n); else if(flag=-2) printf(Error: n The direct item is already full !n); else if(flag=-3) printf(Error: n The number of openfile is too much !n); else if(flag=-4) printf(Error: n The name is already in the direct !n); else if(flag=-5) 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 18 页 - - - - - - - - - printf(Error: n The disk space is full!n); else printf(Successfully create a file! n); show(); break; case 2:/打开文件scanf(%s,name); fd = open(name); if(fd = -1) printf(Error: n The open file not exit! n); else if(fd = -2) printf(Error: n The file have already opened! n); else if(fd = -3) printf(Error: n The number of open file is too much! n); else if(fd = -4) printf(Error: n It is a direct,can not open for read or write! n); else printf(Successfully opened! n); show(); break; case 3:/关闭文件scanf(%s,name); flag = close(name); if(flag = -1) printf(Error:n The file is not opened ! n); else printf(Successfully closed! n); show(); break; case 4:/写文件if(fd =-1) printf(Error:n The file is not opened ! n); else printf(Please input the file contect:); scanf(%s,contect); flag=write(fd,contect,strlen(contect); if(flag = 0) printf(Successfully write! n); else 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 15 页,共 18 页 - - - - - - - - - printf(Error:n The disk size is not enough! n); show(); break; case 5:/读文件if(fd =-1) printf(Error:n The file is not opened ! n); else flag = read(fd,contect); if(flag = 0) for(i=0;iu_opentable.openitemfd.size;i+) printf(%c,contecti); printf(tn); show(); break; case 6:/删除文件scanf(%s,name); flag = del(name); if(flag = -1) printf(Error:n The file not exit! n); else if(flag = -2) printf(Error:n The file is opened,please first close it ! n); else if(flag = -3) printf(Error:n The delete is not file ! n); else printf(Successfully delete! n); show(); break; case 7:/创建子目录scanf(%s,name); flag = mkdir(name); if(flag = -1) printf(Error:n The length of name is to long! n); else if(flag = -2) printf(Error:n The direct item is already full ! n); else if(flag