操作系统课设总结--简单的linux文件仿真系统

来源:互联网 发布:数据透视表 编辑:程序博客网 时间:2024/06/07 07:25

       刚看到这个题目的时候感觉应该不是特别难,但是真的开始下手去写的时候却觉得好像无从下手,要考虑的细节太多太多惊恐......不过,让我们暂且放下对效率对细节的苛求,先用最简单的数据结构和最基础的语句来模拟一个粗糙的linux文件管理系统吧。奋斗(有更高要求的话可以在这个粗糙的仿真系统上进行修改,都是从简单到复杂的不是吗^-^!)

仿真linux文件管理系统,需要着重考虑以下五个方面:1、仿真磁盘(超级块、inode区、目录区、数据区),并且编写磁盘管理程序;2、文件目录树的管理;3、用户活动表、系统打开表、活动inode表以及文件共享相关问题;4、文件的操作(读、写、创建、删除、重命名...)以及权限管理;5、用户管理。

以下是我定义的主要数据结构:文件目录树采用的是二叉树(左子树为子文件,右子树为同级文件)、当前路径用栈表示、为简单起见大多数的采用数组的方式实现,inode区和目录区为512块,数据区为20500块;最多创建10个用户、每个用户最多打开25个文件、系统打开表和活动inode表最多200个...

<span style="font-size:18px;">typedef struct    //用户管理表{char username[10];                      //用户名char password[10];                     //密码char level;                           //级别,只区分root (1) 和 普通用户 (0)int userid;                           //用户号,-1为空(从0开始)int group;                           //组号(1/2/3)  }usernote,* userpoint;typedef struct //命令行信息{ char com[10];}Sys_cmd,* Sys_cmd_point; //超级块信息,均采用顺序分配法(位示图法分配)typedef struct block_super//超级块,使用成组链接法来表示空闲块信息{ char phydata[20500];    //物理块分配情况char inode_info[512];   //inode区分配情况char dir_info[512];       //目录区分配情况int number_inode;             //inode空闲块int number_dir;             //dir空闲块int number_data;             //data空闲块//其余信息对于本次模拟用处不大,因此这里省略,但是写报告的时候可以写上^_^!}super_block;typedef struct// inode信息  { int inode_number;   //inode号int file_style;// 文件类型 0代表文件类型是目录文件 1代表文件类型是普通文件 int file_length;// 文件长度  char file_mode[9];// 读写权限  int file_userid;// 所属用户int file_groupid;// 所属组别int file_address[15];  // 文件的物理地址,3级索引int file_icount;//是否有链接,目录文件无硬链接,普通文件有硬链接char dir_name[10];// 文件所在的目录(父目录)} inode;typedef struct dir// 文件信息(目录块){ char file_name[10];// 文件名  int  dir_inode;// 文件的结点号,从0开始  }dir;typedef struct physical_block//定义存放文件的数据块,每块1024B,但出于对系统测试的需求,按照10即可{char p[10];}physicalBlock;//P315,用户打开表和系统打开表,内存活动inode表typedef struct //系统打开表项{int  f_inode;//指针,指向活动i结点int  f_count;       //文件是否共享//int  f_flags;      //文件读写的标志(暂时没有用)}SystemOpenTable;typedef struct user_opentable//用户打开表项{int point[25];//用户打开文件指针(指向系统打开表项)(每个用户最多打开25个文件)}UserOpenTable;typedef struct active_node//活动inode表{inode activeinode[200];//用数组表示活动inode表}ActiveNode;typedef struct TNode               //文件树(兄弟二叉树){dir data;                       //当前文件struct TNode *lchild,*rchild;                 //左孩子为当前目录下的文件(子文件),右孩子为在同一目录下的文件(兄弟)}FTree,* FTreepoint;typedef struct{char data[10];}path;            typedef struct  //用顺序栈来保存当前的文件路径{path *base;path *top;int stacksize;}SqStack;</span>
定义好这些数据结构之后,接下来我们要做的就是用这些数据结构来构建我们的系统。当然第一步就是初始化系统:1、初始化磁盘(系统文件存在:读入并加载磁盘存在内存中;不存在:新建系统文件并初始化磁盘);2、初始化用户(用户文件存在:读入文件内容;不存在:创建文件并增加一个系统用户(自己指定));3、初始化路径(初始化栈)(默认root\);4、根据目录区内容初始化目录文件树(先序变量递归构建目录文件树);5、初始化文件表项(刚刚打开系统肯定都为空)。

//初始化系统操作,如果有系统文件就读取,如果没有就通过调用各初始化函数初始化系统void InitSystem(FILE *fp){//如果文件存在读取,如果文件不存在就初始化if(fp==NULL){ InitDisks();//首次生成时初始化磁盘} else { ReadFromFile(fp);   // 读取系统文件的内容 } InitUsers();//初始化用户InitTable();//初始化文件表项InitCommand();InitStack(cur_dir);      //初始化路径push(cur_dir,"root");InitfileTree(L_Ftree);}// 初始化磁盘,将超级块,数据块,inode节点以及目录区初始化,组编号和盘块编号均从1开始void InitDisks() { int i,j,num=1; lv_superblock.number_data=20500;lv_superblock.number_dir=512;lv_superblock.number_inode=512;for (i=0;i<512;i++){lv_superblock.inode_info[i]=0;lv_superblock.dir_info[i]=0;}for (i=0;i<20500;i++){lv_superblock.phydata[i]=0;}//超级块初始化完毕// inode结点信息初始化,由于当前无文件打开,则全值为-1,inode号为本身在数组中的下标for(i=0;i<512;i++)      { for(j=0;j<9;j++) { file_inode[i].file_mode[j]=-1;// 读写权限  } for(j=0;j<15;j++) { file_inode[i].file_address[j]=-1;// 文件物理地址  } for(j=0;j<15;j++) { file_inode[i].dir_name[j]=-1;// 文件所在目录  } file_inode[i].inode_number=-1;file_inode[i].file_length=-1;  // 文件长度 file_inode[i].file_style=-1;  // 文件类型file_inode[i].file_icount=-1;file_inode[i].file_userid=-1;file_inode[i].file_groupid=-1;} for(i=0;i<512;i++)     // 根目录区信息初始化{ strcpy(file_dir[i].file_name,"");   //文件名file_dir[i].dir_inode=-1;                       //文件节点号} for(i=0;i<20500;i++)     // 存储文件具体内容块初始化 { for(j=0;j<10;j++) { phy[i].p[j]=-1; } } } //初始化用户设置,有文件就读取,没有文件就创建void InitUsers(){FILE *fps;// 判断用户信息文件是否存在,如果用户文件存在,就通过read函数将用户的信息从文件中读取并存入User数据结构中if((fps=fopen("users.txt","rb"))==NULL)   {L_user[0].userid=0;//不存在,则初始化1个用户,userid从0开始strcpy(L_user[0].username,"lff");strcpy(L_user[0].password,"19213105");//strcpy(L_user[0].username,"1");//strcpy(L_user[0].password,"1");L_user[0].group=1;L_user[0].level=1;//除了初始化时生成的超级管理员之外,其余用户空间都值为负值,等待用户创建for(int i=1;i<10;i++){L_user[i].userid=-1;strcpy(L_user[i].username,"");//用户名以及密码都设置为空strcpy(L_user[i].password,"");L_user[i].group=-1;L_user[i].level=-1;}//调用Save函数将用户的信息存入User.txt文件SaveUsers(fps);}else{//读出系统用户ReadUsers(fps);fclose(fps);}}//初始化系统文件表项、用户文件表项、活动节点void InitTable(){int i,j ;//由于系统刚启动时才会执行,此时没有文件正处于打开状态,于是活动i结点以及用户表,系统表都应该为空//为三个表项的所有值赋负值,以象征空值.//为用户表的指针设置负值for( i=0;i<10;i++ ){for( j=0;j<25;j++ ){user_open_table[i].point[j]=-1 ;}}//文件名为空,文件数为负值,系统打开表为空for(i=0; i<200; i++){sys_open_table[i].f_inode=-1 ;sys_open_table[i].f_count=-1 ;//sys_open_table[i].f_flags=-1 ;}//活动i结点个数为0,指针为负值for(i=0;i<200;i++){for(j=0;j<9;j++) { active_indoe_table.activeinode[i].file_mode[j]=-1;// 读写权限  } for(j=0;j<15;j++) { active_indoe_table.activeinode[i].file_address[j]=-1;// 文件物理地址  } for(j=0;j<15;j++) { active_indoe_table.activeinode[i].dir_name[j]=-1;// 文件所在目录  } active_indoe_table.activeinode[i].inode_number=-1;active_indoe_table.activeinode[i].file_length=-1;  // 文件长度 active_indoe_table.activeinode[i].file_style=-1;  // 文件类型active_indoe_table.activeinode[i].file_icount=-1;active_indoe_table.activeinode[i].file_userid=-1;active_indoe_table.activeinode[i].file_groupid=-1;}}
void InitfileTree(FTreepoint &T)    //该函数的作用是初始化的时候根据dir区构建文件树{<span style="white-space:pre"></span>int a=0;<span style="white-space:pre"></span>T=(FTree *)malloc(sizeof(FTree));//根节点没有在存储区开辟空间,默认加载在内存中,右子树为空<span style="white-space:pre"></span>strcpy(T->data.file_name,"root");<span style="white-space:pre"></span>T->lchild=T->rchild=NULL;<span style="white-space:pre"></span>if (find_num_of_file()>0)<span style="white-space:pre"></span>{<span style="white-space:pre"></span>CreatBiTree1(T->lchild,a);   //0代表从dir区第几个开始<span style="white-space:pre"></span>}}void CreatBiTree1(FTreepoint &T,int& num) //递归方法,按照先序遍历顺序构建文件树{<span style="white-space:pre"></span>if (num>=find_num_of_file())<span style="white-space:pre"></span>{<span style="white-space:pre"></span>return;<span style="white-space:pre"></span>}<span style="white-space:pre"></span>T=(FTree *)malloc(sizeof(FTree));<span style="white-space:pre"></span>T->lchild=T->rchild=NULL;<span style="white-space:pre"></span>T->data.dir_inode=file_dir[num].dir_inode;<span style="white-space:pre"></span>strcpy(T->data.file_name,file_dir[num].file_name);<span style="white-space:pre"></span>num++;<span style="white-space:pre"></span>if (strcmp(file_inode[find_inode_from_name(file_dir[num].file_name)].dir_name,T->data.file_name)==0)   //当前文件的子文件<span style="white-space:pre"></span>{<span style="white-space:pre"></span>CreatBiTree1(T->lchild,num);<span style="white-space:pre"></span>}<span style="white-space:pre"></span>if (strcmp(file_inode[find_inode_from_name(file_dir[num].file_name)].dir_name,file_inode[find_inode_from_name(T->data.file_name)].dir_name)==0) //和当前文件的父文件一样<span style="white-space:pre"></span>{<span style="white-space:pre"></span>CreatBiTree1(T->rchild,num);<span style="white-space:pre"></span>}}
int InitStack(SqStack &S)  //初始化路径,默认初始大小为100{<span style="white-space:pre"></span>S.base=(path*)malloc((100)*sizeof(path));<span style="white-space:pre"></span>if(!S.base)exit(-2);<span style="white-space:pre"></span>S.top=S.base;<span style="white-space:pre"></span>S.stacksize=100;<span style="white-space:pre"></span>return 1;}
初始化完成之后,大致的框架已经搭建完成啦!接下来我们要做的就是实现各种功能啦!当然要编写一个无限循环的函数来模拟shell函数实现各种功能:

//运行函数,主要提供从界面读取用户操作,并将其与初始化的命令参数比较,执行相对应的操作.void shell(FILE *fp){int i,p;        //p为指令号char com[10],tmp[10];  //com暂存当前输入指令,tmp为指令的参数while(1){if(!login())return;while(1)//进入文件系统{printf("[%s]@/",cur_user.username); find_path(cur_dir);printf(">");scanf("%s",com);       // 输入命令并且查找命令的相关操作 for(i=0;i<22;i++)       { if(strcmp(com,cmd[i].com)==0) { p=i; break; } } if(i==22)//输入的命令不正确{ p=22;} switch(p) { case 0: WriteToFile(fp);  return;     //关机case 1: help();         break;     //打印命令信息case 2: show_curdir();  break;    //显示当前文件内容 case 3: scanf("%s",tmp);  go_dir(tmp);  break;     //进入指定目录       case 4: back_dir();   break;   //回到上层目录 case 5: scanf("%s",tmp); create_dir(tmp);break; //创建目录 case 6: scanf("%s",tmp);  del_dir(tmp);break;  //删除目录case 7: scanf("%s",tmp);  create_file(tmp);break;   //创建文件case 8: scanf("%s",tmp);  open_file(tmp);break;  //打开文件case 9: scanf("%s",tmp);  read_file(tmp);break;  //读文件case 10: scanf("%s",tmp);  write_file(tmp);break;   //写文件case 11: scanf("%s",tmp);   close_file(tmp);   break;   //关闭文件case 12: scanf("%s",tmp);  delete_file(tmp);  break;   //删除文件  case 13: show_info();  break;   //查看系统信息 case 14: logout(fp);    break;  //注销 case 15: scanf("%s",tmp);    //切换用户if(change_user(fp,tmp))break;else return;case 16: scanf("%s",tmp); change_mode(tmp);break;   //更改文件访问权限case 17: manage_user();break;   //管理用户case 18: scanf("%s",tmp);h_link(tmp);break;   //硬链接case 19: scanf("%s",tmp);s_link(tmp);break; //软连接case 20: scanf("%s",tmp);rename(tmp);break;   //重命名case 21: system("cls");break;   //清屏//case 22: break;   //扩展用default: printf("输入错误!\n");break;   //输入出错 } } }}
接下来当然就是逐个实现我们的功能啦,还真不少哦!不过其实其中好多都是类似的,实现一个后其他的只用修修补补就可以啦!

太多啦,今天先不写啦,大家参考源代码吧!
http://download.csdn.net/detail/u012989568/9441146

2 0
原创粉丝点击