#include "stdio.h" #include <stdlib.h> //#include <conio.h> #include <string.h> #include"unistd.h" 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("已经初始化完毕 "); printf("进入linux文件系统模拟............ "); } 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;i<length;i++) { k=50-super_block.n; //超级块中表示空闲块的指针 m=super_block.free[k]; //栈中的相应盘块的地址 p=super_block.free[49]; //栈中的最后一个盘块指向的地址 if(m==-1||memory[p].a==1) //检测是否还有下一组盘块 { printf("内存不足,不能够分配空间 "); callback(length); break; } if(super_block.n==1) { memory[m].a=1; //将最后一个盘块分配掉 physic[i]=m; super_block.n=0; for(j=0;j<memory[m].n;j++) //从最后一个盘块中取出下一组盘块号写入栈中 { super_block.free[j]=memory[m].free[j]; super_block.n++; } continue; //要跳过这次循环,下面的语句在IF中已经执行过 } physic[i]=m; //栈中的相应盘块的地址写进 文件地址缓冲区 memory[m].a=1; super_block.n--; } } void create_file(char filename[],int length) //创建文件 { int i,j; for(i=0;i<640;i++) { if(strcmp(filename,root[i].file_name)==0) { printf("文件已经存在,不允许建立重名的文件 "); 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;j<length;j++) { i_node[i].file_address[j]=physic[j]; } break; } } } void 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;j<i_node[k].file_length;j++) { physic[j]=i_node[k].file_address[j]; } callback(i_node[k].file_length); //调用 回收函数 for(j=0;j<100;j++) //删除文件后要将文件属性和目录项的各个值恢复初值 { i_node[k].file_address[j]=-1; //地址恢复初值 } strcpy(root[i].file_name,""); //文件名恢复初值 root[i].i_num=-1; //目录项的I结点信息恢复初值 strcpy(root[i].dir_name,""); //目录项的文件目录信息恢复初值 i_node[k].file_length=-1; //文件长度恢复 i_node[k].file_style=-1; //文件类型恢复初值 break; } } if(i==640) { printf("不存在这个文件 "); } } void 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("目录不为空不能直接删除 "); break; } } if(j==640) { del_file(filename); break; } break; } } if(i==640) { printf("这个不是目录文件 或者不存在这个目录,或者你要删除的是当前目录 "); } } void display_curdir() //显示当前目录下的文件列表 { int i,k; printf(" 文件名字 文件类型 文件长度 所属目录 "); for(i=0;i<640;i++) { if(strcmp(cur_dir,root[i].dir_name)==0) //查询文件中 所在目录信息和当前目录信息相同的数据 { k=root[i].i_num; printf(" %s ",root[i].file_name); //文件名 printf(" %d ",i_node[k].file_style); //文件的类型 printf("%d ",i_node[k].file_length); //文件的长度 printf("%s ",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("没有这个目录 "); } } void open_file(char filename[]) //打开文件 { int i,j,k; printf(" 文件名字 文件类型 文件长度 所属目录 "); 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(" %s ",root[i].file_name); //文件名 printf(" %d ",i_node[k].file_style); //文件的类型 printf("%d ",i_node[k].file_length); //文件的长度 printf("%s ",root[i].dir_name); //文件所在的目录 printf(" 文件占用的物理地址 "); for(j=0;j<i_node[k].file_length;j++) //显示物理地址 { printf("%d ",i_node[k].file_address[j]); //文件具体占用的盘块号 } printf(" "); break; } } if(i==640) { printf("没有这个文件 或者这个文件不是正规文件 "); } } void 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("空闲的盘块数是: "); printf("%d ",k); printf("使用的盘块数是: "); printf("%d ",m); } void help() //显示帮助信息 { printf("注意:创建的文件长度 < 100 "); //说明文件 printf("0.初始化-------------------------format "); printf("1.查看当前目录文件列表-----------dir "); printf("2.创建文件---------------------create-----(create + 空格 + 文件名 + 文件长度) "); printf("3.打开文件-----------------------cat-----(cat + 空格 + 文件名) "); printf("4.删除文件-----------------------del-----(del + 空格 + 文件名) "); printf("5.创建目录-----------------------md------(md + 空格 + 目录名) "); printf("6.删除目录-----------------------deldir--(del + 空格 + 目录名) "); printf("7.进入当前目录下的指定目录-------cd--------(cd + 空格 + 目录名) "); printf("8.返回上一级目录-----------------cd.. "); printf("9.查看系统信息-------------------ls "); printf("10.显示帮助命令-----------------help "); printf("11.退出文件模拟------------------exit "); } 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,"create"); 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,"exit"); if((fp=fopen("system","rb"))==NULL) //判断系统文件是否存在 { printf("can not open file "); printf("format the disk Y / 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("这个不是正规文件文件 "); } 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("没有这个命令 "); break; } } }