#include "stdio.h"
#include <stdlib.h>
//#include <conio.h>
#include <string.h>
#include"unistd.h" int physic[]; //文件地址缓冲区
int style=; //文件的类型
char cur_dir[]="root"; //当前目录 struct command
{
char com[];
}cmd[]; struct block
{
int n; //空闲的盘快的个数
int free[]; //存放空闲盘快的地址
int a; //模拟盘快是否被占用
}memory[]; struct block_super
{
int n; //空闲的盘快的个数
int free[]; //存放进入栈中的空闲块
int stack[]; //存放下一组空闲盘快的地址
}super_block; struct node //i结点信息
{
int file_style; //i结点 文件类型
int file_length; //i结点 文件长度
int file_address[]; //i结点 文件的物理地址
} i_node[]; struct dir //目录项信息
{
char file_name[]; //文件名
int i_num; //文件的结点号
char dir_name[]; //文件所在的目录
} root[]; void format() //格式化
{
int i,j,k;
super_block.n=;
for(i=;i<;i++) //超级块初始化
{
super_block.free[i]=i; //存放进入栈中的空闲块
super_block.stack[i]=+i; //存放下一组的盘块
} for(i=;i<;i++) //i结点信息初始化
{
for(j=;j<;j++)
{
i_node[i].file_address[j]=-;//文件地址
}
i_node[i].file_length=-; //文件长度
i_node[i].file_style=-; //文件类型
} for(i=;i<;i++) //根目录区信息初始化
{
strcpy(root[i].file_name,"");
root[i].i_num=-;
strcpy(root[i].dir_name,"");
}
for(i=;i<;i++) //存储空间初始化
{
memory[i].n=; //必须有这个
memory[i].a=;
for(j=;j<;j++)
{
memory[i].free[j]=-;
}
}
for(i=;i<;i++) //将空闲块的信息用成组链接的方法写进每组的最后一个块中
{ //存储空间初始化 if((i+)%==)
{
k=i+;
for(j=;j<;j++)
{
if(k<)
{
memory[i].free[j]=k;//下一组空闲地址
memory[i].n++; //下一组空闲个数 注意在memory[i].n++之前要给其赋初值
k++;
}
else
{
memory[i].free[j]=-;
}
}
memory[i].a=; //标记为没有使用
continue; //处理完用于存储下一组盘块信息的特殊盘块后,跳过本次循环
}
for(j=;j<;j++)
{
memory[i].free[j]=-;
}
memory[i].n=;
}
printf("已经初始化完毕\n");
printf("进入linux文件系统模拟............\n");
} void write_file(FILE *fp) //将信息读入系统文件中
{
int i;
fp=fopen("system","wb");
for(i=;i<;i++)
{
fwrite(&memory[i],sizeof(struct block),,fp);
}
fwrite(&super_block,sizeof(struct block_super),,fp); for(i=;i<;i++)
{
fwrite(&i_node[i],sizeof(struct node),,fp);
}
for(i=;i<;i++)
{
fwrite(&root[i],sizeof(struct dir),,fp);
}
fclose(fp);
} void read_file(FILE *fp) //读出系统文件的信息
{
int i;
fp=fopen("system","rb");
for(i=;i<;i++)
{
fread(&memory[i],sizeof(struct block),,fp);
} fread(&super_block,sizeof(struct block_super),,fp); for(i=;i<;i++)
{
fread(&i_node[i],sizeof(struct node),,fp);
} for(i=;i<;i++)
{
fread(&root[i],sizeof(struct dir),,fp);
}
fclose(fp);
} void callback(int length) //回收磁盘空间
{
int i,j,k,m,q=;
for(i=length-;i>=;i--)
{
k=physic[i]; //需要提供要回收的文件的地址
m=-super_block.n; //回收到栈中的哪个位置
if(super_block.n==) //注意 当super_block.n==50时 m=-1;的值
{ //super_block.n==50的时候栈满了,要将这个栈中的所有地址信息写进下一个地址中
for(j=;j<;j++)
{
memory[k].free[j]=super_block.free[j];
}
super_block.n=;
memory[k].n=;
}
memory[k].a=;
if(m==-)
{
m=; //将下一个文件地址中的盘块号回收到栈底中,这个地址中存放着刚才满栈的地址的信息
}
super_block.free[m]=physic[i]; //将下一个文件地址中的盘块号回收到栈中
super_block.n++;
}
} void allot(int length) //分配空间
{
int i,j,k,m,p;
for(i=;i<length;i++)
{
k=-super_block.n; //超级块中表示空闲块的指针
m=super_block.free[k]; //栈中的相应盘块的地址
p=super_block.free[]; //栈中的最后一个盘块指向的地址
if(m==-||memory[p].a==) //检测是否还有下一组盘块
{
printf("内存不足,不能够分配空间\n");
callback(length);
break;
}
if(super_block.n==)
{
memory[m].a=; //将最后一个盘块分配掉
physic[i]=m;
super_block.n=;
for(j=;j<memory[m].n;j++) //从最后一个盘块中取出下一组盘块号写入栈中
{
super_block.free[j]=memory[m].free[j];
super_block.n++;
}
continue; //要跳过这次循环,下面的语句在IF中已经执行过
}
physic[i]=m; //栈中的相应盘块的地址写进 文件地址缓冲区
memory[m].a=;
super_block.n--;
}
} void create_file(char filename[],int length) //创建文件
{
int i,j;
for(i=;i<;i++)
{
if(strcmp(filename,root[i].file_name)==)
{
printf("文件已经存在,不允许建立重名的文件\n");
return;
}
}
for(i=;i<;i++)
{
if(root[i].i_num==-)
{
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=;j<length;j++)
{
i_node[i].file_address[j]=physic[j];
}
break;
}
}
} void create_dir(char filename[]) //创建目录
{
style=; //0代表文件类型是目录文件
create_file(filename,);
style=; //用完恢复初值,因为全局变量,否则
}
void del_file(char filename[]) //删除文件
{
int i,j,k;
for(i=;i<;i++)
{ if(strcmp(filename,root[i].file_name)==)
{
k=root[i].i_num;
for(j=;j<i_node[k].file_length;j++)
{
physic[j]=i_node[k].file_address[j];
}
callback(i_node[k].file_length); //调用 回收函数
for(j=;j<;j++) //删除文件后要将文件属性和目录项的各个值恢复初值
{
i_node[k].file_address[j]=-; //地址恢复初值
}
strcpy(root[i].file_name,""); //文件名恢复初值
root[i].i_num=-; //目录项的I结点信息恢复初值
strcpy(root[i].dir_name,""); //目录项的文件目录信息恢复初值
i_node[k].file_length=-; //文件长度恢复
i_node[k].file_style=-; //文件类型恢复初值
break;
}
}
if(i==)
{
printf("不存在这个文件\n");
}
} void del_dir(char filename[]) //删除目录 需要判断目录下时候为空,不为空就不删除
{
int i,j,k;
for(i=;i<;i++) //还要加条件判断要删除的目录是不是当前目录
{
k=root[i].i_num; //找到目录名字
if( strcmp(root[i].file_name,filename)== && strcmp(cur_dir,filename)!= && (i_node[k].file_style)== )
{ for(j=;j<;j++)
{
if(strcmp(filename,root[j].dir_name)==)
{
printf("目录不为空不能直接删除\n");
break;
}
}
if(j==)
{
del_file(filename);
break;
} break;
}
}
if(i==)
{
printf("这个不是目录文件 或者不存在这个目录,或者你要删除的是当前目录\n");
} }
void display_curdir() //显示当前目录下的文件列表
{
int i,k;
printf("\t\t文件名字 文件类型 文件长度 所属目录\n");
for(i=;i<;i++)
{
if(strcmp(cur_dir,root[i].dir_name)==) //查询文件中 所在目录信息和当前目录信息相同的数据
{
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=;i<;i++)
{
k=root[i].i_num; //判断文件类型是不是目录类型
if((strcmp(filename,root[i].file_name)==) && (i_node[k].file_style==))
{
strcpy(cur_dir,filename); //将要进入的指定目录设置为当前目录 赋值不要反了strcpy(目的,源)
break;
}
}
if(i==)
{
printf("没有这个目录\n");
}
}
void open_file(char filename[]) //打开文件
{
int i,j,k;
printf("\t\t文件名字 文件类型 文件长度 所属目录\n");
for(i=;i<;i++)
{
k=root[i].i_num;
if(strcmp(filename,root[i].file_name)== && (i_node[k].file_style==))
{
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=;j<i_node[k].file_length;j++) //显示物理地址
{
printf("%d ",i_node[k].file_address[j]); //文件具体占用的盘块号
}
printf("\n");
break;
}
}
if(i==)
{
printf("没有这个文件 或者这个文件不是正规文件\n");
}
} void back_dir() //返回上一级目录
{
int i,k;
for(i=;i<;i++) //查询和当前目录名相同的目录文件名
{
k=root[i].i_num;
if(strcmp(cur_dir,root[i].file_name)== && (i_node[k].file_style==))
{
strcpy(cur_dir,root[i].dir_name); //将查询到的目录文件名 所在的目录赋值给当前目录
}
}
}
void display_sys() //显示系统信息(磁盘使用情况)
{
int i,m,k=;
for(i=;i<;i++)
{
if(memory[i].a==)
k++;
}
m=-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[],com[],tmp1[],k;
struct command tmp2[];
int i, j=,p,len=;
FILE *fp;
help();
strcpy(cmd[].com,"format"); //将各个命令存进命令表
strcpy(cmd[].com,"dir");
strcpy(cmd[].com,"cat");
strcpy(cmd[].com,"ls");
strcpy(cmd[].com,"md"); strcpy(cmd[].com,"create");
strcpy(cmd[].com,"del");
strcpy(cmd[].com,"deldir");
strcpy(cmd[].com,"cd");
strcpy(cmd[].com,"cd..");
strcpy(cmd[].com,"help");
strcpy(cmd[].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()
{
j=; //必须重新给恢复0否则出错
strcpy(tmp,cur_dir);
while(strcmp(tmp,"root")!=)
{
for(i=;i<;i++)
{
p=root[i].i_num;
if(strcmp(tmp,root[i].file_name)== && (i_node[p].file_style==))
{
strcpy(tmp2[j].com,tmp);
j++;
strcpy(tmp,root[i].dir_name);
}
}
} strcpy(tmp2[j].com,tmp);
for(i=j;i>=;i--)
{
printf("%s/",tmp2[i].com);
} scanf("%s",com); //输入命令并且查找命令的相关操作
for(i=;i<;i++)
{
if(strcmp(com,cmd[i].com)==)
{
p=i;
break;
}
}
if(i==) //如果没有这个语句以后输入的命令都和第一次输入的效果一样
{
p=; //随便的一个值
}
switch(p)
{
case : format(); //初始化
break;
case : display_curdir(); //查看当前目录下的文件列表
break;
case : scanf("%s",tmp); //查看文件
open_file(tmp);
break;
case : display_sys(); //查看系统信息
break;
case :scanf("%s",tmp); //创建目录
create_dir(tmp);
break;
case : scanf("%s",tmp); //创建文件
scanf("%d",&len);
create_file(tmp,len);
break;
case : scanf("%s",tmp); //删除文件
for(i=;i<;i++) //判断文件是不是正规文件
{
j=root[i].i_num;
if(strcmp(tmp,root[i].file_name)== && (i_node[j].file_style)==)
{
del_file(tmp);
break;
}
}
if(i==)
{
printf("这个不是正规文件文件\n");
}
break;
case :
scanf("%s",tmp); //删除目录
del_dir(tmp);
break;
case : scanf("%s",tmp1); //进入当前目录下的指定目录 相当于进入目录 cd + 目录名
display_dir(tmp1);
break;
case : back_dir(); //返回上一级目录
break;
case :help();
break;
case :write_file(fp); //将磁盘利用信息写进系统文件,退出
return;
default:printf("没有这个命令\n");
break;
}
}
}

linux文件系统模拟的更多相关文章

  1. Linux实战教学笔记08:Linux 文件的属性(上半部分)

    第八节 Linux 文件的属性(上半部分) 标签(空格分隔):Linux实战教学笔记 第1章 Linux中的文件 1.1 文件属性概述(ls -lhi) linux里一切皆文件 Linux系统中的文件 ...

  2. Linux文件查找.md

    Linux 文件查找 在Linux系统的查找相关的命令: which 查看可执行文件的位置 whereis 查看文件的位置 locate 配合数据库查看文件位置 find 实际搜寻硬盘查询文件名称 w ...

  3. Linux 文件压缩与归档

    .note-content { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeit ...

  4. Linux文件类型

    1.windows系统和Linux系统的区别 windows通过问价扩展名来区分文件类型,例如*.txt是一个文本文件, linux系统文件的扩展名和文件类型没有关系 为了容易区分文件类型,linux ...

  5. 修改linux文件权限

    Linux系统中的每个文件和目录都有访问许可权限,用它来确定谁可以通过何种方式对文件和目录进行访问和操作. 文件或目录的访问权限分为只读,只写和可执行三种.以文件为例,只读权限表示只允许读其内容,而禁 ...

  6. Linux文件和目录权限详细讲解

    转载请标明出处: http://www.cnblogs.com/why168888/p/5965180.html 本文出自:[Edwin博客园] Linux文件和目录权限解读 如何设置Linxu文件和 ...

  7. linux 文件系统结构及命令

    1.linux 文件系统结构 / 根目录 root |--mnt/ | |--sdcard/  挂载点 | |--usb0 | |--cdrom |--home | |--soft01 <- 用 ...

  8. linux 文件权限、类型、命名规则

    文件权限 -rwxr-x--t        文件类型 用户权限 组权限 其他用户权限 umask是一个掩码,设置文件的默认权限,会屏蔽掉不想授予该安全级别的权限,从对象的全权权限中减掉:对文件全权权 ...

  9. linux文件权限查看及修改(实用)

    查看Linux文件的权限:ls -l 文件名称 查看linux文件夹的权限:ls -ld 文件夹名称(所在目录) 修改文件及文件夹权限: sudo chmod -(代表类型)×××(所有者)×××(组 ...

随机推荐

  1. GridView自定义分页

    CSS样式 首先把CSS样式代码粘贴过来: .gv { border: 1px solid #D7D7D7; font-size:12px; text-align:center; } .gvHeade ...

  2. ListView中多个EditText设置焦点 多次点击异常报错

    08-17 18:23:09.825: ERROR/AndroidRuntime(1608): FATAL EXCEPTION: main 08-17 18:23:09.825: ERROR/Andr ...

  3. IOS开发之——OpenUDID的使用获取用户唯一设备

    下载网址:https://github.com/ylechelle/OpenUDID OpenUDID测试结果分析 1)优点: a.没有用到MAC地址.MAC地址跟UDID一样,存在隐私问题.不能保证 ...

  4. 记录毕业论文 LanguageTool 二次开发时用到的网站

    LanguageTool Development LanguageTool Supported Languages Share your knowledge about LT - LanguageTo ...

  5. Python3常用内置函数

    数学相关 abs(a) : 求取绝对值.abs(-1) max(list) : 求取list最大值.max([1,2,3]) min(list) : 求取list最小值.min([1,2,3]) su ...

  6. jsonp的后台怎么返回去数据

  7. 05.C#泛型类型(三章3.1-3.2)

    接下来说下C#中的泛型,熟练地使用泛型能提高代码的重用性,使用我们代码瞬间就高大上了,当然只有一点点,真的只有一点点,因为后面要学习和掌握的知识还有很多.先来看下一个使用Dictionary<T ...

  8. java--- Map详解

    Map简介 将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值.此接口取代 Dictionary 类,后者完全是一个抽象类,而不是一个接口. Map 接口提供三种collecti ...

  9. 利用Ant脚本生成war包的详细步骤

    使用ant脚本前的准备 1.下载一个ant安装包.如:apache-ant-1.8.4-bin.zip.解压到E盘. 2.配置环境变量.新增ANT_HOME:E:\apache-ant-1.8.4:P ...

  10. Eclipse_调试技巧

    一.使用Display视图实时计算变量结果(带智能提示)  windows-->show view-->display http://stackoverflow.com/questions ...