2022年实验文件系统模 .pdf
实验 4 文件系统模拟实验 4 文件系统模拟一、实验目的:设计和实现基于FAT12的模拟磁盘卷及其 I/O 系统的文件存取操作基本功能函数, 深入领会和理解文件系统的体系结构、工作原理和设计要领。二、实验设计1. 根据 FAT12设计模拟磁盘( 1.44MB 软盘映像文件)的磁盘组织结构及文件或空闲盘块管理方法与描述用数据结构,并实现模拟磁盘的创建和格式化操作。2. 设计和实现模拟磁盘I/O 操作暨物理盘块与缓冲区 (缓冲区与物理盘块大小相同)间数据交互的两个函数。3. 构建和提供用户与文件系统之间的基本接口,包括目录和文件的创建、重命名、删除和显示操作, 目录的进入操作以及文件的定位及读、写操作。4. 测试系统功能并给出有效证据。三、源程序清单和说明名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 13 页 - - - - - - - - - 实验 4 文件系统模拟#include #include #include #define BlockSize 512 #define DirSize 32 #define RootSize 2 struct ReserveBlock int sysblocknum;/* 文件系统总扇区数*/ int resblocknum;/* 保留扇区扇区数*/ int fatblocknum;/*FA T 表扇区数 */ int rootblocknum;/* 根目录区扇区数*/ char fillcharBlockSize-4*sizeof(int);/*填充字节 */ ; struct DirBlock char filename11; /* 文件名限长 11个字符 */ char fillcharDirSize-4*sizeof(int)-sizeof(long int)-11;/* 填充字节 */ long filelen; /* 文件长度 */ int year,month,day; /* 日期 */ int firstblockaddr; /*文件首块扇区号*/ ; struct FCBBlock int fileid; /*文件标识 */ struct DirBlock fileinfo; /*目录信息 */ long filepos; /* 文件读写指针 */ int fdtblockaddr; /*目录项所在块号 */ int fdtblockindex; /* 目录项所在块内序号 */ struct FCBBlock *next;/* 指向下一个文件控制块的指针*/ ; struct ReserveBlock sys1; struct FCBBlock *fcb; struct DirBlock fil32,*dir;/*目录项 */ int *fat1; char *str,*ptr; char fillcharBlockSize; FILE *fp; FILE *OPENSYS(char *filename) int i; fp=fopen(filename,rb+); fread(&sys1,1,BlockSize,fp); fat1=(int *)malloc(sys1.sysblocknum); for(i=0;i10) printf( 文件名过长 n); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 13 页 - - - - - - - - - 实验 4 文件系统模拟printf( 请重新输入 :); scanf(%s,filename); else break; while(1) for(i=0;i32;i+) if(strcmp(filename,fili.filename)=0) printf( 该文 件 名已 存 在n); printf( 请重新输入 :); flag1=1; break; if(flag1=0) break; scanf(%s,filename); flag1=0; for(i=(sys1.fatblocknum+sys1.resblocknum+sys1.rootblocknum);isys1.sysblocknum;i+) if(fat1i=0) flag+;/* 统计磁盘上为空数目*/ if(flag=0) printf( 磁盘已满 );/* 统计结果为0,则磁盘已满 */ return 0; printf( 空闲块数 :%dn,flag); printf( 请输入文件长度:); for(j=0;j32;j+) if(filj.firstblockaddr=0) break; while(1) scanf(%d,&dirj.filelen);/*输入 目录项中文件的长度*/ n=(dirj.filelen/BlockSize)+(dirj.filelen%BlockSize?1:0); if(nflag)/* 文件长度小于0 或大于空闲的空间*/ printf( 文件长度过长 n); printf( 请重新输入 :); else break; for(i=(sys1.fatblocknum+sys1.resblocknum+sys1.rootblocknum);i=n)/*n 文件长度 */ fat1m=i+1; fat1i=-1; break; else fat1m=i+1; m=i; strcpy(dirj.filename,filename); dirj.filenamea=0; printf( 请输入年份 :); scanf(%d,&dirj.year); printf( 请输入月份 :); scanf(%d,&dirj.month); printf( 请输入日期 :); scanf(%d,&dirj.day); return (1); void LISTDIR(void)/*显示目录 */ int i,flag=0; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 13 页 - - - - - - - - - 实验 4 文件系统模拟for(i=0;ifdtblockindex.filename)=0)/* 目录项所在内序号*/ printf( 文件已经打开, 请先关闭文件n); return 0; else p=p-next; for(i=0;i32;i+)/*查找要关闭的文件*/ if(strcmp(filename,fili.filename)=0) flag=1; break; if(flag=0) printf( 文件不存在 n); return 0; j=fili.firstblockaddr; while(1) k=fat1j-1; fseek(fp,(j-1)*BlockSize,0);/*将 指 针 指向文件的第一个扇区的位置*/ fwrite(&fillchar,1,BlockSize,fp); fat1j-1=0; if(k=-1) break; else j=k; memset(&fili,0,DirSize); return 1; int FOPEN(char *filename)/*打开文件 */ int i,j=0,k,flag=0; struct FCBBlock *p,*q,*r; p=fcb; for(i=0;ifdtblockindex.filename)=0) printf( 文件已打开 n); return 0; q=p; p=p-next; if(fcb=NULL) fcb=(struct FCBBlock *)malloc(sizeof(struct FCBBlock); fcb-fileid=j+1;/*文件标示 */ fcb-filepos=0;/* 文件读写指针*/ 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 13 页 - - - - - - - - - 实验 4 文件系统模拟fcb-next=NULL;/*指 向下一 个文件控制指针*/ fcb-fdtblockindex=i; else r=(struct FCBBlock *)malloc(sizeof(struct FCBBlock); r-fileid=j+1; r-filepos=0; r-next=NULL; r-fdtblockindex=i; q-next=r; /*f-next=NULL; */ return 1; long FGETLEN(int fileid)/*获取文件指针*/ struct FCBBlock *p; p=fcb; while(p) if(p-fileid=fileid)/*寻找要找的指针*/ return(p-filepos); p=p-next; printf(errorn); return(0); int FCLOSE(char *filename)/*关闭文件*/ int flag=0; struct FCBBlock *f,*p; f=fcb; if(strcmp(filename,filfcb-fdtblockindex.filename)=0) flag=1; fcb=fcb-next; p=fcb; while(p) p-fileid-=1; p=p-next; return flag; p=f; f=f-next; while(f) if(strcmp(filename,filf-fdtblockindex.filename)=0) flag=1; p=f-next; /*p=p-next;*/ while(p) p=p-next; p-fileid-=1; free(f); return flag; p=f; f=f-next; if(flag=0) printf( 文件未打开 n); return flag; return 0; int FREAD(char *str, int n, int fileid)/*文件块读*/ int m,i,j=0,k,l,len; char a3; struct FCBBlock *p; p=fcb; while(p) if(p-fileid=fileid) break; else p=p-next; len=filp-fdtblockindex.filelen;/*文 件长度 */ l=p-filepos;/* 文件读写指针:该块在文件的相对位置 */ 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 13 页 - - - - - - - - - 实验 4 文件系统模拟printf( 现在打开文件 :); printf(%dn,l); printf( 是否读入这个文件?(Y/N):); scanf(%s,a); if(a0=n|a0=N) printf( 输入内容 :); while(1) scanf(%d,&l); if(filp-fdtblockindex.filelenfilp-fdtblockindex.filelen) printf(too large!n); printf(input read size,again:); scanf(%d,&n); else break; str=(char *)malloc(filp-fdtblockindex.filelen+1); m=(len/BlockSize)+(len%BlockSize?1:0); k=filp-fdtblockindex.firstblockaddr; if(m1) fseek(fp,(k-1)*BlockSize,0); fread(str,BlockSize,1,fp); k=fat1k-1; for(i=1;ifilepos=n+l; printf(%sn,str); return 1; void FWRITE(char *ptr, int n, int fileid) char a3; long l; int m,i=0,j,k=0,num,flag=0,flag1=0,b; struct FCBBlock *p; p=fcb; while(p) if(p-fileid=fileid) break; else p=p-next; l=p-filepos; printf( 现在打开文件 :); printf(%dn,l); printf( 是否写入这个文件?(Y/N):); scanf(%s,a); if(a0=n|a0=N) printf( 输入内容 :); while(1) scanf(%d,&l); if(filp-fdtblockindex.filelenfdtblockindex.firstblockaddr; for(i=1;iBlockSize ) if(flag1=0) fwrite(&ptr0,j*BlockSize-l,1,fp); flag1=1; else fwrite(&ptrj*BlockSize-l+k*BlockSize,BlockSize,1,fp); else m=j*BlockSize-l+(k-1)*BlockSize; b=n-(j*BlockSize-l+(k-1)*BlockSize); fwrite(&ptrm,b,1,fp); k+; i+; while(n+l)-(i-1)*BlockSize)1); p-filepos=l+n; int FEOF(int fileid) int flag; struct FCBBlock *p; p=fcb; while(p) if(p-fileid=fileid) break; if(p-fileposfilp-fdtblockindex.filelen) return 0; else return 1; long FGETPOS(int fileid) struct FCBBlock *p; p=fcb; while(p) if(p-fileid=fileid) return (p-filepos); else p=p-next; printf(error!n); return(0); int FSETPOS(int fileid, long offset) struct FCBBlock *p; p=fcb; while(p) if(p-fileid=fileid) while(offsetfilp-fdtblockindex.filelen|offsetfile lengthn); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 13 页 - - - - - - - - - 实验 4 文件系统模拟printf(input file pos ,again:); scanf(%d,offset); p-filepos=offset; return 1; else p=p-next; printf(error!n); return(0); void DISPLAY() printf( 请输入命令 :n); printf( 建立文件 :creatn); printf( 显示目录 :listn); printf( 删除文件 :deln); printf( 打开文件 :openn); printf( 关闭文件 :closen); printf( 文件块读 :readn); printf( 文件块写 :writen); printf( 退出:exitn); void test(char *filename) char *t,cmd10,fname12; struct FCBBlock *p; int i,j,n,flag,len,id,flag1=0; fp=OPENSYS(filename); while(1) DISPLAY(); scanf(%s,cmd); if(!strcmp(cmd,creat) printf( 请输入文件名:n); scanf(%s,fname); flag=FCREATE(fname); if(flag=1) printf(文 件%s 创 建 成 功n,fname); else if(!strcmp(cmd,list) LISTDIR(); else if(!strcmp(cmd,del) scanf(%s,fname); flag=FDELETE(fname); if(flag=1) printf(文 件%s 删 除 成 功n,fname); else if(!strcmp(cmd,open) scanf(%s,fname); flag=FOPEN(fname); if(flag=1) printf( 文件 %s 打开n,fname); else if(!strcmp(cmd,close) scanf(%s,fname); flag=FCLOSE(fname); if(flag=1) printf( 文件 %s 关闭n,fname); else if(!strcmp(cmd,read) scanf(%s,fname); p=fcb; flag1=0; while(p) if(!strcmp(filp-fdtblockindex.filename,fname) printf( 请输入文件大小:); scanf(%d,&len); id=p-fileid; flag=FREAD(str,len,id); flag1=1; p=p-next; if(flag1=0) printf( 文件%s 未打开,请先打开文件n,fname); else if(!strcmp(cmd, write) scanf(%s,fname); p=fcb; flag1=0; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 13 页 - - - - - - - - - 实验 4 文件系统模拟while(p) if(!strcmp(filp-fdtblockindex.filename,fname) printf( 请输入文件大小:); do scanf(%d,&len); if(lenfilp-fdtblockindex.filelen) printf( 文件长度过大, 请重新输入: ); while(lenfilp-fdtblockindex.filelen); id=p-fileid; ptr=(char *)malloc(len); scanf(%s,ptr); FWRITE(ptr,len,id); flag1=1; p=p-next; if(flag1=0) printf( 文件%s 未打开,请先打开文件n,fname); else if(!strcmp(cmd,exit) flag=CLOSESYS(fp); break; else printf(error!n); int main(void) struct ReserveBlock sys; char filename=fatsys.dat; int *fat; int i,j; fcb=NULL; memset(&sys,255,BlockSize); printf( 请输入索要创建的文件系统的大小(532767):); scanf(%d,&(sys.sysblocknum); sys.resblocknum=1; sys.fatblocknum=sys.sysblocknum/(BlockSize/sizeof(int)+ (sys.sysblocknum%(BlockSize/sizeof(int)?1:0); fat=(int*)malloc(BlockSize*sys.fatblocknum); memset(fat,255,BlockSize*sys.fatblocknum); memset(fat,0,sizeof(int)*sys.sysblocknum); sys.rootblocknum=RootSize; j=sys.resblocknum+sys.fatblocknum+sys.rootblocknum; for (i=0;ij;i+) fati=-1; memset(&fillchar,0,BlockSize); fp=fopen(filename,w+b); fwrite(&sys,1,BlockSize,fp); for (i=0;isys.fatblocknum;i+) fwrite(fat+i*BlockSize/sizeof(int),1,BlockSize,fp); j=sys.resblocknum+sys.fatblocknum; for(i=0;i(sys.sysblocknum-j);i+) fwrite(&fillchar,1,BlockSize,fp); fclose(fp); free(fat); test(filename); return 0; 四、算法及关键数据结构设计1. 模拟磁盘的格式化操作名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 13 页 - - - - - - - - - 实验 4 文件系统模拟2. 磁盘 I/O 操作模拟函数readBlock(int i, char *p); 该函数把 i#逻辑块的内容读入到指针p 指向的盘块缓冲(注意读入计数处理)。writeBlock(int i, char *p); 该函数把指针 p 指向的盘块缓冲内容写入到i#逻辑块(注意写入计数处理)。3. 系统原型测试创建目录和文件足够多和足够大,使系统功能测试完整彻底。尝试交叉使用虚拟机上的DOS 系统和系统原型接口对所创建的软盘映像文件进行查看和执行文件或目录的各种操作。五、实验过程中间结果屏幕截图1. 程序运行输入文件系统大小名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 13 页 - - - - - - - - - 实验 4 文件系统模拟文件体系建立成功,可执行以下操作2. 创建文件名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 13 页 - - - - - - - - - 实验 4 文件系统模拟3. 显示文件目录4. 删除文件删除后文件目录:5. 打开文件打开成功:打开失败6. 关闭文件7. 写文件8. 读文件名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 13 页 - - - - - - - - - 实验 4 文件系统模拟六、疑难解惑及经验教训本次实验实现了基于FAT12的模拟磁盘卷及其 I/O 系统的文件存取操作基本功能函数。通过本次实验进一步理解了文件系统的体系结构,工作原理和设计要领。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 13 页 - - - - - - - - -