操作系统课设(文件管理)
目录
一、设计目的、意义
二、设计分析
三、方案分析
四、功能模块实现
五、设计体会
六、源代码
一、设计目的、意义 1.通过模拟文件系统的实现,深入理解操作系统中文件系统的理论知识, 加深对教材中的重要算法的理解。同时通过编程实现这些算法,更好地掌握操作系统的原理及实现方法,提高综合运用各专业课知识的能力。 2.意义:本文件系统采用多级目录,其中第一级对应于用户账号,第二级对应于用户账号下的文件,第三级对应文件夹下的文件,以此类推。另外,为了简单本文件系统未考虑文件共享、文件系统安全以及管道文件与设备文件等特殊内容。 二、设计分析 ①用户登录 用户分为超级管理员、管理员和普通用户。超级管理员具有创建用户并设置权限的权限; 管理员与超级管理员权限基本相同。 ②建立文件 模拟文件系统进行“建立文件”的处理。 ③打开文件 约定操作类型与文件属性不符合和正处在“建立”状态的文件不允许打开。 ④关闭文件 对某个文件不需要再读或写的时候,用户应关闭该文件。 ⑤读文件 文件打开后可顺序读文件中的记录,读长度表示本次操作需读的记录个数。 ⑥写文件 执行写文件操作时要区分两种情况,第一种是在执行create后要求写,第二种是执行open后要求写。对第二种情况可认为用户要对一个已建立好的文件进行修改。一个文件可以分多次写,既可按记录顺序写也可随机写一个记录,采用顺序写时可省略记录号。 ⑦文件列表 将目前本用户本路径的文件列出,并列出相关的属性。 ⑧结束 退出程序,返回原有操作系统。 三、方案分析 3.1:主要的数据结构 通过分析课程设计要求,具体设计出如下数据结构: //用户类型定义 struct user { char name[10];//用户名 int pride;//用户权限,1为管理员,0为普通用户 char pass[10];//用户密码 }; //定义空白区项 struct freeb { int number; struct freeb * next; }; //定义文件打开项 struct fileb { int parent;//所在父节点 char name[15];//文件名 int pride;//读写权限,0只读,1读写 int rex;//读写状态,0为没有,1读2写 struct fileb * next; }; //定义文件索引项 struct findex { char name[15]; int number; int parent; char kind; struct findex * next; }; //定义目录表项 struct dreitem { char name[25];//目录或者文件名称 int parent;//上层目录 int pride;//文件操作权限,0只读,1读写 int empty;//是否是空闲块,0为空闲块,1为非空 };
3.2:流程图
3.2.1主流程图:
四、功能模块实现 4.1 login() 登陆: 用户输入用户名和密码,在user文件中查找是否有此用户,核对密码。正确则登陆成功,当前目录设定到当前用户文件夹下。 4.2 createuser() 新建用户: 先根据提示输入用户名,再判断此用户名是否已存在,若存在则重新输入,若没有,则用户创建成功。函数结束。 4.3 intlist() 初始化空闲区链表以及文件索引链: 本函数在程序用运行后,对空闲区进行初始化。 4.4 newdrec() 新建目录: 输入参数为要建立的类型,f为文件,d为文件夹。并输入权限(0只读,1读写)。在创建目录时,并检测是否有重名的目录,若有则创建失败;没有重名的就在空闲区添加,否则,直接在文件中添加。 4.5 lsfile() 列出当前路径下的文件: 查找当前目录下的各种文件并列举出来。 4.6 back() 目录后退: 检测当前是否处于根目录下,不是则返回到上一目录;若当前处于根目录下,则无法后退。 五、设计体会 第一、操作系统这次课程设计让我学习到了很多计算机方面的知识,在一定程度上对以前的所学知识进一步加深,更让我有了一个系统的了解。操作系统是计算机的软件的系统的基础,具有一定平台性。掌握好这门课程对我们以后学习计算机知识有一个很大的帮助。 第二、本次课程设计让我明白了编写程序一定要动手去写代码,进行实际操作方可进取得一定性的进步。
第二种方法:https://www.cnblogs.com/byczyz/p/12873304.html 六、附录 源代码: #include <bits/stdc++.h> #define getb(type) (type*)malloc(sizeof(type)) using namespace std; int usernowpride;//全局变量,当前用户类型 char usernowname[10];//全局变量,当前用户名 int nowlevel=-1; //全局变量,当前目录层次 char usernowpath[200] = "\\\0"; struct user //用户类型定义 { char name[10];//用户名 char pass[10];//用户密码 int pride;//用户权限,1为管理员,0为普通用户 }; struct freeb //定义空白区项 { int number; struct freeb * next; }; struct freeb *fblk=NULL;//全局变量,系统空闲区链 struct fileb //定义文件打开项 { int parent;//所在父节点 char name[15];//文件名 int pride;//读写权限,0只读,1读写 int rex;//读写状态,0为没有,1读2写 struct fileb * next; }; struct fileb *flink=NULL;//全局变量,系统打开文件链 struct findex //定义文件索引项 { char name[15]; int number; int parent; struct findex * next; }; struct findex *fidx=NULL;//全局变量,文件索引链 struct dreitem //定义目录表项 { char name[25];//目录或者文件名称 int parent;//上层目录 int pride;//文件操作权限,0只读,1读写 int empty;//是否是空闲块,0为空闲块,1为非空 }; bool login();//用户登录模块 void intlist();//初始化空闲区链表以及文件索引链 bool createuser();//新建用户 void logout();//用户注销模块 void lsfile();//列出用户的文件 void newdrec();//新建目录 void disfilelist();//显示当前打开文件列表 void openfile();//打开文件 void closefile();//关闭文件 void rwfile(int ch);//读写文件,该文件必须先打开后才可以进行读写操作 bool back();//目录后退 void delete1();//删除文件 int main() { int choince; while(1) { system("cls"); while(1) if(login())//判断用户是否登录 break; //默认的管理账号密码是root 123456.用户账号可以进行相应的操作 if(strcmp(usernowname,"root")==0) { system("cls"); printf("root管理员\n"); printf("*****************\n"); printf("1.新建用户 2.注销\n"); printf("*****************\n"); bool lout=false; while(1) { fflush(stdin); scanf("%d",&choince); switch(choince) { case 1:createuser();break; case 2:char out;printf("真的要注销吗?(y OR n):"); fflush(stdin);scanf("%c",&out); if(out=='y'||out=='Y') { lout=true; logout(); } break; default: printf("Error:错误命令\n"); break; } if(lout) break; } } else{ intlist(); system("cls"); cout<<"当前用户:\n"<<usernowname; cout<<"****************\n"; printf("1.文件列表\n2.新建文件\n3.打开文件\n4.关闭文件\n"); printf("5.读文件\n6.写文件\n7.回退上层\n8.删除文件\n9.注销\n"); printf("***************\n"); bool lout=false; while(1) { fflush(stdin); scanf("%d",&choince); switch(choince) { case 1:lsfile();break; case 2:newdrec();intlist();break; case 3:openfile();disfilelist();break; case 4:closefile();disfilelist();break; case 5:rwfile(1);break; case 6:rwfile(2);break; case 7:back();break; case 8:delete1();break; case 9:char out;printf("真的要注销吗?(y OR n):"); fflush(stdin); scanf("%c",&out); if(out=='y'||out=='Y') { lout=true; logout(); } break; default: printf("Error:错误命令\n"); break; } if(lout) break; } } } printf("完成\n"); return 0; } //目录后退 bool back() { if(nowlevel==-1) { cout<<"Error:当前已为用户根目录,无法再回退\n"; return false; } char name[15]; int i; i=nowlevel; struct dreitem drecnow; FILE *fp; fp=fopen(usernowname,"rb"); fseek(fp,i*sizeof(struct dreitem),0); fread(&drecnow,sizeof(struct dreitem),1,fp); fclose(fp); strcpy(name,drecnow.name); nowlevel=drecnow.parent; char cc; //检测'\0'位置 int ccidx=0; //记录最好一个'\'位置 int j=0; cc=usernowpath[j]; while(cc!='\0') { j++; cc=usernowpath[j]; if(cc=='\\') { ccidx=j; } } if(ccidx!=0) { usernowpath[ccidx]='\0'; } return true; } //读写文件,该文件必须先打开后才可以进行读写操作 void rwfile(int ch) { char name[15]; cout<<"要操作的文件名:"; cin>>name; if(flink==NULL||flink->next==NULL) { cout<<"Error:该文件尚未打开\n"; return; } fileb *fb=flink; while(fb!=NULL&&fb->next!=NULL) { fb=fb->next; if((strcmp(fb->name,name)==0)&&(fb->parent==nowlevel)) { //char ch; if(fb->rex!=ch&&fb->rex!=0) { if(ch==2) { if(fb->pride!=1) { cout<<"Error:该文件只读,没有写权限\n"; return; } else cout<<"当前文件正在读进程,是否终止读进程进行写?(y OR n):"; } else cout<<"当前文件正在写进程,是否终止写进程进行读?(y OR n):"; fflush(stdin); cin>>ch; if(ch=='y'||ch=='Y') { if(ch==2) { fb->rex=1; cout<<"文件正在读...\n"; } else { fb->rex=2; cout<<"文件正在写...\n"; } } } else { if(ch==2&&fb->pride!=1) { cout<<"Error:该文件只读,没有写权限\n"; return; } fb->rex=ch; if(ch==1) cout<<"文件正在读...\n"; else cout<<"文件正在写...\n"; } return; } } } //关闭文件 void closefile() { char name[15]; cout<<"输入要关闭的文件:"; cin>>name; if(flink==NULL||flink->next==NULL) { cout<<"Error:该文件没有打开\n"; return; } fileb *fb=flink; fileb *ffb=NULL; while(fb!=NULL&&fb->next!=NULL) { ffb=fb; fb=fb->next; if((strcmp(fb->name,name)==0)&&(fb->parent==nowlevel)) { ffb->next=fb->next; free(fb); cout<<"文件已经关闭\n"; return; } } cout<<"Error:当前路径下找不到你要关闭的文件,请确定文件名已经路径是否正确\n"; } //打开文件 void openfile() { long ep; int i=0; FILE *fp; struct dreitem drenow; char name[15]; cout<<"输入要打开的文件名:"; cin>>name; struct fileb *fb=flink; while(fb!=NULL&&fb->next!=NULL) { fb=fb->next; if((strcmp(fb->name,name)==0)&&(fb->parent==nowlevel)) { cout<<"Error:该文件已经打开\n"; return; } } fp=fopen(usernowname,"rb"); //可用索引节点 fseek(fp,0,2); ep=ftell(fp); fseek(fp,0,0); while(ep!=ftell(fp)) { fread(&drenow,sizeof(struct dreitem),1,fp); if((strcmp(drenow.name,name)==0)&&(drenow.parent==nowlevel)) { //添加到打开链表 fileb *pb=getb(struct fileb); strcpy(pb->name,name); pb->parent=nowlevel; pb->next=NULL; pb->rex=0; pb->pride=drenow.pride; if(flink==NULL) { flink=getb(struct fileb); flink->next=pb; } else { pb->next=flink->next; flink->next=pb; } cout<<"文件已经打开\n"; fclose(fp); //这里是否要更新显示已打开链表 return; } i++; } cout<<"Error:当前目录下无此文件,请核对\n"; fclose(fp); } //执行删除文件的操作 void delete1(){ char name[15]; cout<<"输入要删除的文件名:"; cin>>name; long ep; FILE *fp; struct dreitem drenow; fp=fopen(usernowname,"rb"); fseek(fp,0,2); ep=ftell(fp); fseek(fp,0,0); cout<<"文件名\t文件权限\t上层目录\n"; while(ep!=ftell(fp)) { fread(&drenow,sizeof(struct dreitem),1,fp); if(strcmp(drenow.name,name)==0) continue; if(drenow.parent==nowlevel&&drenow.empty!=0) { cout<<drenow.name<<"\t"; cout<<drenow.pride<<"\t"; cout<<drenow.parent<<"\n"; } } fclose(fp); } //显示当前打开文件列表 void disfilelist() { if(flink==NULL||flink->next==NULL) { cout<<"当前打开文件队列空\n"; return; } else { cout<<"当前打开文件队列如下:(文件名|父节点|读写权限|读写状态)\n"; fileb *fb=flink; while(fb!=NULL&&fb->next!=NULL) { fb=fb->next; printf("%s|%d|%d|%d->",fb->name,fb->parent,fb->pride,fb->rex); } cout<<"**\n"; } } void newdrec()//新建目录 { struct dreitem dnow; char name[15]; char pride;//权限,0只读,1读写 int i;//记录空闲区区号 bool cancrd = true;//用于判断是否有重名文件 cout<<"请输入名字:"; fflush(stdin); scanf("%s",&name); //判断是否已经存在相同名字的文件或者目录 struct findex *fi=fidx; cout<<"请输入权限(0只读,1读写):"; cin>>pride; strcpy(dnow.name,name); dnow.empty=0; dnow.parent=nowlevel; if(pride=='0') dnow.pride=0; else dnow.pride=1; dnow.empty=1; FILE *fp; if(!(fp=fopen(usernowname,"rb+"))) { cout<<"错误"; return ; } else { if(fblk==NULL||fblk->next==NULL) //空闲区没有就直接在文件添加 { fseek(fp,0,2); fwrite(&dnow,sizeof(struct dreitem),1,fp); cout<<"创建成功\n"; fclose(fp); return; } else { struct freeb *p=fblk->next;//拿第一个空闲区来存放文件 if(p!=NULL) { //fblk=p->next; i = p->number; fblk->next=p->next; } free(p); fseek(fp,i*sizeof(struct dreitem),0); fwrite(&dnow,sizeof(struct dreitem),1,fp); cout<<"创建成功\n"; fclose(fp); return; } } } //列表当前路径下的文件 void lsfile() { long ep; FILE *fp; struct dreitem drenow; fp=fopen(usernowname,"rb"); fseek(fp,0,2); ep=ftell(fp); fseek(fp,0,0); //打开每个用户的存储信息,然后获取文件信息。 cout<<"文件名\t文件权限\t上层目录\n"; while(ep!=ftell(fp)) { fread(&drenow,sizeof(struct dreitem),1,fp); if(drenow.parent==nowlevel&&drenow.empty!=0) { cout<<drenow.name<<"\t"; cout<<drenow.pride<<"\t"; cout<<drenow.parent<<"\n"; } } cout<<"文件列表结束\n"; fclose(fp); } //注销 void logout() { strcpy(usernowname," "); nowlevel=-1; fblk=NULL; fidx=NULL; strcpy(usernowpath,"\\"); flink=NULL; } //新建用户 bool createuser() { struct user newuser; char name[10]; char pass[10]; int pride; if(usernowpride!=1) { cout<<"当前用户没有新建用户的权限\n"; return false; } FILE *fp; if((fp = fopen("user","ab+"))==NULL) { cout<<"用户表打开失败\n"; return false; } else { cout<<"请输入用户名:"; cin>>name; if(strcmp(name,"root")==0) { printf("Error:此为超级管理员\n"); return false; } rewind(fp); while(!feof(fp)) { fread(&newuser,sizeof(struct user),1,fp); if(strcmp(newuser.name,name)==0) { cout<<"该用户名已经存在\n"; fclose(fp); return false; } } cout<<"请输入用户密码:"; cin>>pass; cout<<"请输入用户权限(0普通用户,1管理员):"; cin>>pride; strcpy(newuser.name,name); strcpy(newuser.pass,pass); newuser.pride=pride; //为新建用户建立用户目录文件 if(!fopen(newuser.name,"ab+")) { cout<<"用户创建失败\n"; //如创建失败则把已经建立的用户目录删除 char cmd[20] = "DEL "; strcat(cmd,newuser.name); system(cmd); fclose(fp); return false; } if(!fwrite(&newuser,sizeof(struct user),1,fp)) { cout<<"创建失败\n"; fclose(fp); return false; } else { cout<<"用户创建成功\n"; fclose(fp); return true; } } } //初始化空闲区链表以及文件索引链 void intlist() { //清空各链表 fidx=NULL; fblk=NULL; int i=0; struct dreitem dnow;//文件目录的表项 FILE *fp;//文件指针操作 if(!(fp=fopen(usernowname,"rb")))//打开当前用户的文件(每个用户可能设置的文件是不一样的) { cout<<"Error:打开用户目录失败\n"; return ; } else { int enp; int sp; fseek(fp,0,2);//文件指针偏离操作 enp=ftell(fp);//获取指针的位置 fseek(fp,0,0); sp=ftell(fp); if(sp==enp) return;//如果相等表示还没有登录需要进行登录操作 while(!feof(fp))//feof()结束返回非0 { fread(&dnow,sizeof(struct dreitem),1,fp);//开始读取 if(dnow.empty==0) { //把空闲区连到空闲链表中 struct freeb *fb =getb(struct freeb); fb->number=i; fb->next=NULL; struct freeb *p=fblk; if(p==NULL) { fblk=getb(struct freeb); fblk->next=fb; } else { while(p->next!=NULL) { p=p->next; } p->next=fb; } //完成初始化的任务 } else { //建立索引表 struct findex *fi =(struct findex*)malloc(sizeof(struct findex)); strcpy(fi->name,dnow.name); fi->number=i; fi->parent=dnow.parent; fi->next=NULL; struct findex *pi=fidx; if(pi==NULL) { fidx=getb(struct findex); fidx->next=fi; } else { while(pi->next!=NULL) { pi=pi->next; } pi->next=fi; } } i++; } fclose(fp); return ; } } bool login()//用户登陆 { char name[10]; char pass[10]; cout<<"\n用户名:"; cin>>name; cout<<"\n密 码:"; cin>>pass; if((strcmp("root",name)==0)&&(strcmp("123456",pass)==0))//管理员 { usernowpride = 1; strcpy(usernowname,"root"); return true; } FILE *fp=NULL; struct user actuser; if(!(fp=fopen("user","ab+"))) //ab+ 以二进制方式打开,并在原内容后追加 { cout<<"Error:用户表错误\n"; return false; } rewind(fp); //将文件指针重新指向文件的开头 while(!feof(fp)) //判断指针是否已经到达文件的尾部 { fread(&actuser,sizeof(struct user),1,fp); //把user里的数据读入到actuser中 if((strcmp(actuser.name,name)==0)&&(strcmp(actuser.pass,pass)==0)) { usernowpride = actuser.pride;//记录当前用户的权限 strcpy(usernowname,actuser.name);//记录当前用户的主路径 nowlevel=-1;//记录当前目录层次 fclose(fp); //设置路径 if(strcmp(usernowpath,"\\")!=0) //不是根目录就添加斜杠 strcat(usernowpath,"\\"); strcat(usernowpath,usernowname); return true; } } cout<<"Error:用户名或密码无效,请核对后再输入\n"; fclose(fp); return false; }
一纸高中万里风,寒窗读破华堂空。
莫道长安花看尽,由来枝叶几相同?