#include 'stdio.h'

#include <stdlib.h>
#include <conio.h>
#include <string.h>

int physic[300]; // 文件地址缓冲区,用于存储文件的物理地址 int style=1; // 文件的类型,1表示文本文件,2表示二进制文件

char cur_dir[10]="c"; // 当前目录,初始值为"c"

struct command // 命令结构体 { char com[10]; // 命令名称 }cmd[12];

struct block // 盘块结构体,用于模拟磁盘的存储空间 { int n; // 空闲的盘块的个数 int free[50]; // 存放空闲盘块的地址 int a; // 模拟盘块是否被占用,0表示未被占用,1表示被占用 }memory[200];

struct block_super // 超级块结构体,用于存储空闲盘块的信息 { int n; // 空闲的盘块的个数 int free[50]; // 存放进入栈中的空闲块 int stack[50]; // 存放下一组空闲盘块的地址 }super_block;

struct node // i结点结构体,用于存储文件的相关信息 { int file_style; // i结点文件类型,1表示文本文件,2表示二进制文件 int file_length; // i结点文件长度,即文件占用的盘块数 int file_address[100]; // i结点文件的物理地址,即文件所占用的盘块的地址 } i_node[64];

struct dir // 目录项结构体,用于存储文件的目录信息 { char file_name[10]; // 文件名 int i_num; // 文件的结点号 char dir_name[10]; // 文件所在的目录 } c[64];

void format() // 格式化函数,用于初始化文件系统 { int i,j,k; super_block.n=50; // 超级块中空闲盘块的个数初始值为50 for(i=0;i<50;i++) // 初始化超级块 { super_block.free[i]=i; // 存放进入栈中的空闲块 super_block.stack[i]=50+i; // 存放下一组的盘块 }

for(i=0;i<64;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<64;i++)   // 初始化根目录区信息
{
    strcpy(c[i].file_name,"");          // 文件名
    c[i].i_num=-1;                      // 文件的结点号
    strcpy(c[i].dir_name,"");           // 文件所在的目录
} 

for(i=0;i<200;i++)  // 初始化存储空间
{
    memory[i].n=0;      // 必须有这个
    memory[i].a=0;      
    for(j=0;j<50;j++)
    {
        memory[i].free[j]=-1;  // 存放空闲盘块的地址
    }
}

for(i=0;i<200;i++)  // 将空闲块的信息用成组链接的方法写进每组的最后一个块中
{                   // 存储空间初始化
    if((i+1)%50==0) // 每50个盘块为一组
    {
        k=i+1;
        for(j=0;j<50;j++)
        {
            if(k<200)
            {
                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"); // 打开名为system的二进制文件,以写入方式打开 for(i=0;i<200;i++) // 循环200次,将内存中的200个块写入文件 { fwrite(&memory[i],sizeof(struct block),1,fp); // 将内存中的一个块写入文件,每次写入一个块的大小 } fwrite(&super_block,sizeof(struct block_super),1,fp); // 将超级块写入文件

for(i=0;i<64;i++) // 循环64次,将i节点写入文件 { fwrite(&i_node[i],sizeof(struct node),1,fp); // 将一个i节点写入文件,每次写入一个i节点的大小 } for(i=0;i<64;i++) // 循环64次,将目录项写入文件 { fwrite(&c[i],sizeof(struct dir),1,fp); // 将一个目录项写入文件,每次写入一个目录项的大小 } fclose(fp); // 关闭文件 }

void read_file(FILE fp) / 读出系统文件的信息 */ { int i; fp=fopen("system","rb"); // 打开名为system的二进制文件,以读取方式打开 for(i=0;i<200;i++) // 循环200次,将文件中的200个块读入内存 { fread(&memory[i],sizeof(struct block),1,fp); // 从文件中读取一个块,每次读取一个块的大小 }

fread(&super_block,sizeof(struct block_super),1,fp); // 从文件中读取超级块

for(i=0;i<64;i++) // 循环64次,将i节点读入内存 { fread(&i_node[i],sizeof(struct node),1,fp); // 从文件中读取一个i节点,每次读取一个i节点的大小 }

for(i=0;i<64;i++) // 循环64次,将目录项读入内存 { fread(&c[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--) // 循环length次,回收length个盘块 { 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++) // 循环50次,将栈中的50个盘块号写入下一个文件地址中 { memory[k].free[j]=super_block.free[j]; // 将栈中的盘块号写入下一个文件地址中 } super_block.n=0; // 栈中的盘块号已经全部写入下一个文件地址中,将栈中盘块数清零 memory[k].n=50; // 将下一个文件地址中的盘块数设置为50 } memory[k].a=0; // 将要回收的盘块标记为未使用 if(m==-1) { m=49; / 将下一个文件地址中的盘块号回收到栈底中,这个地址中存放着刚才满栈的地址

信息 / } super_block.free[m]=physic[i]; / 将下一个文件地址中的盘块号回收到栈中 */ super_block.n++; // 栈中的盘块数加1 } }

void allot(int length) /* 分配空间 / { int i,j,k,m,p; for(i=0;i<length;i++) // 循环length次,分配length个盘块 { 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++; // 栈中的盘块数加1 } continue; / 要跳过这次循环,下面的语句在IF中已经执行过 / } physic[i]=m; / 栈中的相应盘块的地址写进 文件地址缓冲区 */ memory[m].a=1; // 将分配的盘块标记为已使用 super_block.n--; // 栈中的盘块数减1 } }

void create_file(char filename[],int length) /* 创建文件 */ { int i,j; for(i=0;i<64;i++) // 循环64次,查找是否有同名文件 { if(strcmp(filename,c[i].file_name)==0) // 如果找到同名文件 { printf("文件已经存在,不允许建立重名的文件\n"); // 输出错误信息 return; // 返回 } } for(i=0;i<64;i++) // 循环64次,查找空闲的目录项 { if(c[i].i_num==-1) // 如果找到空闲的目录项 { c[i].i_num=i; // 将目录项的i节点号设置为i strcpy(c[i].file_name,filename); // 将文件名写入目录项 strcpy(c[i].dir_name,cur_dir); // 将当前目录名写入目录项 i_node[i].file_style=style; // 将文件类型写入i节点 i_node[i].file_length=length; // 将文件长度写入i节点 allot(length); // 分配盘块 for(j=0;j<length;j++) // 循环length次,将盘块号写入i节点 { i_node[i].file_address[j]=physic[j]; } break; // 跳出循环 } } }

void create_dir(char filename[]) /* 创建目录 / { style=0; / 0代表文件类型是目录文件 / create_file(filename,4); // 创建文件,长度为4 style=1; / 用完恢复初值,因为全局变量,否则 / } 能否创建多个目录,是否可以切换目录内容:void show_dir() / 显示当前目录下的文件和目录 */ { int i; printf("\n当前目录为:%s\n",cur_dir); printf("文件名\t\t文件类型\t文件长度\n"); for(i=0;i<64;i++) // 循环64次,查找当前目录下的文件和目录 { if(strcmp(cur_dir,c[i].dir_name)==0) // 如果找到当前目录下的文件或目录 { if(i_node[c[i].i_num].file_style==1) // 如果是文本文件 { printf("%s\t\t文本文件\t%d\n",c[i].file_name,i_node[c[i].i_num].file_length); // 输出文件信息 } else if(i_node[c[i].i_num].file_style==2) // 如果是二进制文件 { printf("%s\t\t二进制文件\t%d\n",c[i].file_name,i_node[c[i].i_num].file_length); // 输出文件信息 } else if(i_node[c[i].i_num].file_style==0) // 如果是目录文件 { printf("%s\t\t目录文件\t%d\n",c[i].file_name,i_node[c[i].i_num].file_length); // 输出目录信息 } } } }

void change_dir(char dirname[]) /* 切换目录 */ { int i; for(i=0;i<64;i++) // 循环64次,查找是否有同名目录 { if(strcmp(dirname,c[i].file_name)==0&&i_node[c[i].i_num].file_style==0) // 如果找到同名目录 { strcpy(cur_dir,c[i].file_name); // 将当前目录名设置为找到的目录名 printf("已经切换到%s目录下\n",cur_dir); // 输出提示信息 return; // 返回 } } printf("目录不存在或者不是目录文件\n"); // 输出错误信息 }

void delete_file(char filename[]) /* 删除文件 */ { int i,j,k; for(i=0;i<64;i++) // 循环64次,查找要删除的文件 { if(strcmp(filename,c[i].file_name)==0) // 如果找到要删除的文件 { if(strcmp(cur_dir,c[i].dir_name)!=0) // 如果要删除的文件不在当前目录下 { printf("文件不存在或者不在当前目录下\n"); // 输出错误信息 return; // 返回 } k=i_node[c[i].i_num].file_length; // 取得要删除的文件长度 for(j=0;j<k;j++) // 循环k次,回收要删除的文件占用的盘块 { physic[j]=i_node[c[i].i_num].file_address[j]; } callback(k); // 回收磁盘空间 i_node[c[i].i_num].file_length=-1; // 将i节点中的文件长度设置为-1,表示该文件已被删除 i_node[c[i].i_num].file_style=-1; // 将i节点中的文件类型设置为-1,表示该文件已被删除 for(j=0;j<k;j++) // 循环k次,将i节点中的文件地址清零 { i_node[c[i].i_num].file_address[j]=-1; } strcpy(c[i].file_name,""); // 将目录项中的文件名清空 c[i].i_num=-1; // 将目录项中的i节点号设置为-1 printf("文件已经被删除\n"); // 输出提示信息 return; // 返回 } } printf("文件不存在或者不在当前目录下\n"); // 输出错误信息 }

void delete_dir(char dirname[]) /* 删除目录 */ { int i,j,k; for(i=0;i<64;i++) // 循环64次,查找要删除的目录 { if(strcmp(dirname,c[i].file_name)==0&&i_node[c[i].i_num].file_style==0

C语言模拟UNIX文件系统

原文地址: https://www.cveoy.top/t/topic/f2se 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录