zoukankan      html  css  js  c++  java
  • linux文件系统模拟

    #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; 
            } 
        } 
    }  

  • 相关阅读:
    BZOJ 1101 莫比乌斯函数+分块
    BZOJ 2045 容斥原理
    BZOJ 4636 (动态开节点)线段树
    BZOJ 2005 容斥原理
    BZOJ 2190 欧拉函数
    BZOJ 2818 欧拉函数
    BZOJ 3123 主席树 启发式合并
    812. Largest Triangle Area
    805. Split Array With Same Average
    794. Valid Tic-Tac-Toe State
  • 原文地址:https://www.cnblogs.com/umgsai/p/3908211.html
Copyright © 2011-2022 走看看