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

原文地址:https://www.cnblogs.com/umgsai/p/3908211.html