操作系统课程设计-成组链接模拟unix文件系统|精品课程网站设计|课程设计网报告总结心得
[问题描述]在任一OS下,建立一个大文件,把它假象成一张盘,在其中实现一个简单的 模拟UNIX文件系统 。[基本要求] 1.在现有机器硬盘上开辟20M的硬盘空间,作为设定的硬盘空间。 2.编写一管理程序对此空间进行管理,以模拟UNIX(linux)文件系统,具体要求如下:(1) 要求盘块大小1k
(2) i 结点文件类型 正规文件目录文件(共1byte)块设备 管道文件 。物理地址(索引表) 共有13个表项,每表项2byte 。文件长度 4byte 。联结计数 1byte (3)0号块 超级块 栈长度50 空闲盘块的管理:成组链接 ( UNIX) 位示图法 (Linux) (4)每建一个目录,分配4个物理块 文件名 14byte (5)目录项信息 i 结点号 2byte
(6)结构: 0#: 超级块 1#-20#号为 i 结点区 20#-30#号为根目录区(7)功能: 1、初始化 2、建立文件(需给出文件名,文件长度) 3、建立子目录 4、打开文件(显示文件所占的盘块) 5、删除文件 6、删除目录 7、显示目录(即显示目录下的信息,包括文件、子目录等) 8、显示整个系统信息 2、模拟文件系统[问题描述] 在任一OS下,建立一个大文件,把它假象成一张盘,在其中实现一个简单的小型文件系统。[基本要求]该小型文件系统没有子目录机制,文件连续分配,不考虑分区。做一个简单的 操作界面,提供四条简单的命令:简单的ls、cat、cp、rd.进一步增强:上题中的文件系统功能:文件系统不连续分配,可以有子目录 机制,(如两级子目录机制)。附录 课程设计报告内容一.实验题目与要求。二.总的设计思想及环境说明、工具等。三.本题所需数据结构与模块说明。四.运行结果与运行情况。五.自我评析与总结。1. 你认为你完成的哪些比较好或比较出色;2. 差距与局限,什么做的不太好或什么地方可以做的更好以待改进;3. 从本作业得到的收获:对编写与调试过程中经验教训的总结;4. 完成本题的其他方法或你的设想;5. 对本实验题的评价和改进意见。
#include "stdio.h" #include
#include #include int physic[100]; //文件地址缓冲区int style=1; //文件的类型char cur_dir[10]="root"; //当前目录 struct command{ char com[10];}cmd[12];
struct block{ int n; //空闲的盘快的个数 int free[50]; //存放空闲盘快的地址 int a; //模拟盘快是否被占用}memory[20449];
struct block_super{ int n; //空闲的盘快的个数 int free[50]; //存放进入栈中的空闲块 int stack[50]; //存放下一组空闲盘快的地址}super_block;
struct node //i结点信息{ int file_style; //i结点 文件类型 int file_length; //i结点 文件长度 int file_address[100]; //i结点 文件的物理地址} i_node[640];
struct dir //目录项信息{ char file_name[10]; //文件名 int i_num; //文件的结点号 char dir_name[10]; //文件所在的目录} root[640];
void format() //格式化{ int i,j,k; super_block.n=50; for(i=0;i<50;i++) //超级块初始化 { super_block.free[i]=i; //存放进入栈中的空闲块 super_block.stack[i]=50+i; //存放下一组的盘块 }
for(i=0;i<640;i++) //i结点信息初始化 { for(j=0;j<100;j++) { i_node[i].file_address[j]=-1;//文件地址 } i_node[i].file_length=-1; //文件长度 i_node[i].file_style=-1; //文件类型 }
for(i=0;i<640;i++) //根目录区信息初始化 { strcpy(root[i].file_name,""); root[i].i_num=-1; strcpy(root[i].dir_name,""); } for(i=0;i<20449;i++) //存储空间初始化 { memory[i].n=0; //必须有这个 memory[i].a=0; for(j=0;j<50;j++) { memory[i].free[j]=-1; }} for(i=0;i<20449;i++) //将空闲块的信息用成组链接的方法写进每组的最后一个块中 { //存储空间初始化 if((i+1)%50==0) { k=i+1; for(j=0;j<50;j++) { if(k<20450) { memory[i].free[j]=k;//下一组空闲地址 memory[i].n++; //下一组空闲个数 注意在memory[i].n++之前要给其赋初值 k++; } else { memory[i].free[j]=-1; } } memory[i].a=0; //标记为没有使用 continue; //处理完用于存储下一组盘块信息的特殊盘块后,跳过本次循环 } for(j=0;j<50;j++) { memory[i].free[j]=-1; } memory[i].n=0; } printf("已经初始化完毕\n"); printf("进入UNIX文件模拟............\n\n");}
void write_file(FILE *fp) //将信息读入系统文件中{ int i; fp=fopen("system","wb"); for(i=0;i<20449;i++) { fwrite(&memory[i],sizeof(struct block),1,fp); } fwrite(&super_block,sizeof(struct block_super),1,fp);
for(i=0;i<640;i++) { fwrite(&i_node[i],sizeof(struct node),1,fp); } for(i=0;i<640;i++) { fwrite(&root[i],sizeof(struct dir),1,fp); } fclose(fp);}
void read_file(FILE *fp) //读出系统文件的信息{ int i; fp=fopen("system","rb"); for(i=0;i<20449;i++) { fread(&memory[i],sizeof(struct block),1,fp); }
fread(&super_block,sizeof(struct block_super),1,fp);
for(i=0;i<640;i++) { fread(&i_node[i],sizeof(struct node),1,fp); }
for(i=0;i<640;i++) { fread(&root[i],sizeof(struct dir),1,fp); } fclose(fp);}
void callback(int length) //回收磁盘空间{ int i,j,k,m,q=0; for(i=length-1;i>=0;i--) { k=physic[i]; //需要提供要回收的文件的地址 m=49-super_block.n; //回收到栈中的哪个位置 if(super_block.n==50) //注意 当super_block.n==50时 m=-1;的值 { //super_block.n==50的时候栈满了,要将这个栈中的所有地址信息写进下一个地址中 for(j=0;j<50;j++) { memory[k].free[j]=super_block.free[j]; } super_block.n=0; memory[k].n=50; } memory[k].a=0; if(m==-1) { m=49; //将下一个文件地址中的盘块号回收到栈底中,这个地址中存放着刚才满栈的地址的信息 } super_block.free[m]=physic[i]; //将下一个文件地址中的盘块号回收到栈中 super_block.n++; }}
void allot(int length) //分配空间{ int i,j,k,m,p; for(i=0;ivoid create_file(char filename[],int length) //创建文件{ int i,j; for(i=0;i<640;i++) { if(strcmp(filename,root[i].file_name)==0) { printf("文件已经存在,不允许建立重名的文件\n"); return; } } for(i=0;i<640;i++) { if(root[i].i_num==-1) { root[i].i_num=i; strcpy(root[i].file_name,filename); strcpy(root[i].dir_name,cur_dir); //把当前目录名 给新建立的文件 i_node[i].file_style=style; i_node[i].file_length=length; allot(length); for(j=0;jvoid create_dir(char filename[]) //创建目录{ style=0; //0代表文件类型是目录文件 create_file(filename,4); style=1; //用完恢复初值,因为全局变量,否则}
void del_file(char filename[]) //删除文件{ int i,j,k; for(i=0;i<640;i++) { if(strcmp(filename,root[i].file_name)==0) { k=root[i].i_num; for(j=0;jvoid del_dir(char filename[]) //删除目录 需要判断目录下时候为空,不为空就不删除{ int i,j,k; for(i=0;i<640;i++) //还要加条件判断要删除的目录是不是当前目录 { k=root[i].i_num; //找到目录名字 if( strcmp(root[i].file_name,filename)==0 && strcmp(cur_dir,filename)!=0 && (i_node[k].file_style)==0 ) { for(j=0;j<640;j++) { if(strcmp(filename,root[j].dir_name)==0) { printf("目录不为空不能直接删除\n"); break; } } if(j==640) { del_file(filename); break; } break; } } if(i==640) { printf("这个不是目录文件 或者不存在这个目录,或者你要删除的是当前目录\n"); } }
void display_curdir() //显示当前目录下的文件列表{ int i,k; printf("\t\t文件名字 文件类型 文件长度 所属目录\n"); for(i=0;i<640;i++) { if(strcmp(cur_dir,root[i].dir_name)==0) //查询文件中 所在目录信息和当前目录信息相同的数据 { k=root[i].i_num; printf("\t\t %s\t",root[i].file_name); //文件名 printf("\t%d\t",i_node[k].file_style); //文件的类型 printf("%d\t",i_node[k].file_length); //文件的长度 printf("%s\n",root[i].dir_name); //文件所在的目录 } }}
void display_dir(char filename[]) //进入指定的目录 { int i,k; for(i=0;i<640;i++) { k=root[i].i_num; //判断文件类型是不是目录类型 if((strcmp(filename,root[i].file_name)==0) && (i_node[k].file_style==0)) { strcpy(cur_dir,filename); //将要进入的指定目录设置为当前目录 赋值不要反了strcpy(目的,源) break; } } if(i==640) { printf("没有这个目录\n"); }}void open_file(char filename[]) //打开文件{ int i,j,k; printf("\t\t文件名字 文件类型 文件长度 所属目录\n"); for(i=0;i<640;i++) { k=root[i].i_num; if(strcmp(filename,root[i].file_name)==0 && (i_node[k].file_style==1)) { printf("\t\t %s\t",root[i].file_name); //文件名 printf("\t%d\t",i_node[k].file_style); //文件的类型 printf("%d\t",i_node[k].file_length); //文件的长度 printf("%s\n",root[i].dir_name); //文件所在的目录 printf("\t\t文件占用的物理地址\n"); for(j=0;jvoid back_dir() //返回上一级目录{ int i,k; for(i=0;i<640;i++) //查询和当前目录名相同的目录文件名 { k=root[i].i_num; if(strcmp(cur_dir,root[i].file_name)==0 && (i_node[k].file_style==0)) { strcpy(cur_dir,root[i].dir_name); //将查询到的目录文件名 所在的目录赋值给当前目录 } }}void display_sys() //显示系统信息(磁盘使用情况){ int i,m,k=0; for(i=0;i<20449;i++) { if(memory[i].a==0) k++; } m=20449-k; printf("空闲的盘块数是:\t"); printf("%d\n",k); printf("使用的盘块数是:\t"); printf("%d\n",m);}
void help() //显示帮助信息{ printf("注意:创建的文件长度 < 100\n\n"); //说明文件 printf("0.初始化-------------------------format\n"); printf("1.查看当前目录文件列表-----------dir\n"); printf("2.查看文件-----------------------cat-----(cat + 空格 + 文件名) \n"); printf("3.查看系统信息-------------------ls \n"); printf("4.创建目录-----------------------md------(md + 空格 + 目录名) \n"); printf("5.创建文件-----------------------vi------(vi + 空格 + 文件名 + 文件长度) \n"); printf("6.删除文件-----------------------del-----(del + 空格 + 文件名) \n"); printf("7.删除目录-----------------------deldir--(del + 空格 + 目录名)\n"); printf("8.进入当前目录下的指定目录-------cd--------(cd + 空格 + 目录名)\n"); printf("9.返回上一级目录-----------------cd.. \n"); printf("10.显示帮助命令-----------------help \n"); printf("11.退出文件模拟------------------quit \n");}void main() //主函数{ char tmp[10],com[10],tmp1[10],k; struct command tmp2[10]; int i, j=0,p,len=0; FILE *fp; help(); strcpy(cmd[0].com,"format"); //将各个命令存进命令表 strcpy(cmd[1].com,"dir"); strcpy(cmd[2].com,"cat"); strcpy(cmd[3].com,"ls"); strcpy(cmd[4].com,"md"); strcpy(cmd[5].com,"vi"); strcpy(cmd[6].com,"del"); strcpy(cmd[7].com,"deldir"); strcpy(cmd[8].com,"cd"); strcpy(cmd[9].com,"cd.."); strcpy(cmd[10].com,"help"); strcpy(cmd[11].com,"quit"); if((fp=fopen("system","rb"))==NULL) //判断系统文件是否存在 { printf("can not open file\n"); printf("format the disk Y / N \n"); scanf("%c",&k); if(k=='y') format(); } else { read_file(fp); //读取系统文件的内容 } while(1) { j=0; //必须重新给恢复0否则出错 strcpy(tmp,cur_dir); while(strcmp(tmp,"root")!=0) { for(i=0;i<640;i++) { p=root[i].i_num; if(strcmp(tmp,root[i].file_name)==0 && (i_node[p].file_style==0)) { strcpy(tmp2[j].com,tmp); j++; strcpy(tmp,root[i].dir_name); } } } strcpy(tmp2[j].com,tmp); for(i=j;i>=0;i--) { printf("%s/",tmp2[i].com); }
scanf("%s",com); //输入命令并且查找命令的相关操作 for(i=0;i<12;i++) { if(strcmp(com,cmd[i].com)==0) { p=i; break; } } if(i==12) //如果没有这个语句以后输入的命令都和第一次输入的效果一样 { p=13; //随便的一个值 } switch(p) { case 0: format(); //初始化 break; case 1: display_curdir(); //查看当前目录下的文件列表 break; case 2: scanf("%s",tmp); //查看文件 open_file(tmp); break; case 3: display_sys(); //查看系统信息 break; case 4:scanf("%s",tmp); //创建目录 create_dir(tmp); break; case 5: scanf("%s",tmp); //创建文件 scanf("%d",&len); create_file(tmp,len); break; case 6: scanf("%s",tmp); //删除文件 for(i=0;i<640;i++) //判断文件是不是正规文件 { j=root[i].i_num; if(strcmp(tmp,root[i].file_name)==0 && (i_node[j].file_style)==1) { del_file(tmp); break; } } if(i==640) { printf("这个不是正规文件文件\n"); } break; case 7: scanf("%s",tmp); //删除目录 del_dir(tmp); break; case 8: scanf("%s",tmp1); //进入当前目录下的指定目录 相当于进入目录 cd + 目录名 display_dir(tmp1); break; case 9: back_dir(); //返回上一级目录 break; case 10:help(); break; case 11:write_file(fp); //将磁盘利用信息写进系统文件,退出 return; default:printf("SORRY,没有这个命令\n"); break; } }}