- #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("已经初始化完毕\n");
- printf("进入linux文件系统模拟............\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;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("内存不足,不能够分配空间\n");
- 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("文件已经存在,不允许建立重名的文件\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;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("不存在这个文件\n");
- }
- }
- 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("目录不为空不能直接删除\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;j<i_node[k].file_length;j++) //显示物理地址
- {
- printf("%d ",i_node[k].file_address[j]); //文件具体占用的盘块号
- }
- printf("\n");
- break;
- }
- }
- if(i==640)
- {
- printf("没有这个文件 或者这个文件不是正规文件\n");
- }
- }
- 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("空闲的盘块数是:\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.创建文件---------------------create-----(create + 空格 + 文件名 + 文件长度) \n");
- printf("3.打开文件-----------------------cat-----(cat + 空格 + 文件名) \n");
- printf("4.删除文件-----------------------del-----(del + 空格 + 文件名) \n");
- printf("5.创建目录-----------------------md------(md + 空格 + 目录名) \n");
- printf("6.删除目录-----------------------deldir--(del + 空格 + 目录名)\n");
- printf("7.进入当前目录下的指定目录-------cd--------(cd + 空格 + 目录名)\n");
- printf("8.返回上一级目录-----------------cd.. \n");
- printf("9.查看系统信息-------------------ls \n");
- printf("10.显示帮助命令-----------------help \n");
- printf("11.退出文件模拟------------------exit \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,"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\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("没有这个命令\n");
- break;
- }
- }
- }