操作系统课设(文件管理)

 

目录

一、设计目的、意义

设计分析

三、方案分析

四、功能模块实现

五、设计体会

源代码

 

一、设计目的、意义
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;
}  

 

 

 

posted @ 2020-05-19 15:47  薄眠抛却陈年事。  阅读(1032)  评论(0编辑  收藏  举报