OS6 文件管理

来源:互联网 发布:linux开机启动 编辑:程序博客网 时间:2024/06/07 21:45

OS6 文件管理

  • 实验
    采用二级文件目录结构,编写程序实现文件系统的文件存储空间的管理、文件的物理结构、目录结构管理和文件操作。
    1、设计一个有m个用户的文件系统,每个用户最多可保存一个文件。
    2、规定用户在一次运行中只能打开K个文件。
    3、系统能检查键入命令的正确性,出错时应能显示出错原因。
    4、对文件应能设置保护措施,如只能执行、允许读、允许写等。
    5、对文件的操作设计提供一套文件操作:
    CREATE建立文件;
    DELETE删除文件;
    OPEN打开文件;
    CLOSE关闭文件;
    READ读文件;
    WRITE写文件。
    6、二级目录结构如下图所示。

    主文件目录MFD

    用户名 用户文件目录地址 user1 root1 … …

    用户文件目录UFD

    文件名 状态(打开/建立 指针 file1 0 (FCB*)file … … …
  • 分析
     为了简单实现,没有对目录进行更多的管理,每个用户仅一个根目录。

    • 数据结构
      除以上的结构外,增加了:
      PM 物理块的页面
      FCB 文件控制块
//简单模拟,不在添加TCB了//物理块const int MAX=4096;const int MAX_OPEN_FILE_USER=2;int page=16;char buf[MAX];//页式管理物理块,sys管理,仅此一份struct PM{    //指向物理块    int base;    //这个长度都是一样的有系统决定    int len;    //next为NULL表示文件结束    PM *next;    bool status;//1 used 0 free};list<PM>pmFree;list<PM>pmUsed;struct FCB{    //文件名字    string name;    //属性  0-r 1-w 2-e    int attribute;    //文件是否打开    int status;//文件新建状态可写入 --2    int len;//文件长度    //物理块位置 --指向页面    PM*next;};struct UFD{    //目录名字    string name;    //1 打开 --没发现怎么用啊 -2代开失败    int status;    int max_open_files;    int num_open_files;    //point to file    list<FCB> file;};struct MFD{    string user;    UFD ufd;};list<MFD>mfd;
  • 算法:

    • 底层的物理块管理
      1、模拟程序申请了一块buf,物理块管理算法,便是对文件的数据存储具体位置的管理。
      2、页式离散分区管理
      listpmFree//空闲页面链表
      listpmUsed//已分配页面链表
      3、程序初始化完成对物理页面的分配
      4、申请PM 从pmFree取一个PM,修改PM.status=1,从pmFree中删除,加入pmUsed
      5、释放PM 修改PM.status=0,从pmUsed删除,加入pmFree。
      当释放的物理块较多时,也可以先修改所有PM的status,然后使用PM同步。
      6.PM同步:将pmUsed中status==0的PM删除,加入到pmFree中。

    • 文件操作
      利用各种属性,对文件操作进行保护性操作。

      • CREATE
        新建文件,填充FCB添加到UFD中,文件状态为2,新建状态的文件可读取写入,不文件读写权限限制。
        第一次使用CLOSE命令后,status=0,此时文件将受文件读写权限控制。
      • DELETE
        删除文件,在检查权限,文件状态,正常后,主要是释放文件所占用的PM,这时的释放,可使用PM同步释放的方式。
        最后讲文件的FCB从UFD中删除即可。
      • OPEN
        检查文件状态和限制后,status=1
      • CLOSE
        status=0
      • WRITE
        检查文件状态和属性,新建状态的可写入,未使用状态,检查文件属性r/e不可写。
        关于写:讲要写入的数据一次,写入文件的PM中,PM不够则申请一个新的PM,链入上一个PM的next指针,
        继续写入内容。为简单实现,程序只有追加写入一种,即只增加PM。
      • READ
        检查文件状态和属性,新建状态可读取,未使用装填,文件属性e不可读。
        读:遍历文件的PM直到PM.next==NULL,每个PM读取位置由PM.base 和PM.len决定。
    • 其他
        实验中,遇到两个自己平常不注意的情况,
      1.标准库中的list,在删除节点后继续迭代对出错,正确方式是,迭代器要赋值为删除节点函数的返回值,之
      后便可继续迭代。
      2.list的节点的指针返回,(TYPE*)(&(it->begin().firstvale));
      3.case标签不能定义变量,解决加个花括号{},在这里边操作。
    • code
#include<iostream>#include<list>using namespace std;//简单模拟,不在添加TCB了//物理块const int MAX=4096;const int MAX_OPEN_FILE_USER=2;int page=16;char buf[MAX];//页式管理物理块,sys管理,仅此一份struct PM{    //指向物理块    int base;    //这个长度都是一样的有系统决定    int len;    //next为NULL表示文件结束    PM *next;    bool status;//1 used 0 free};list<PM>pmFree;list<PM>pmUsed;struct FCB{    //文件名字    string name;    //属性  0-r 1-w 2-e    int attribute;    //文件是否打开    int status;//文件新建状态可写入 --2    int len;//文件长度    //物理块位置 --指向页面    PM*next;};struct UFD{    //目录名字    string name;    //1 打开 --没发现怎么用啊 -2代开失败    int status;    int max_open_files;    int num_open_files;    //point to file    list<FCB> file;};struct MFD{    string user;    UFD ufd;};list<MFD>mfd;void createUser(string name,string dir);void initSys();//分配物理块页面void initPM(int size=16);//模拟中目录只有一个//type:目录or 流文件 void create(string user,string file,int type,int attribute);void del(string user,string file);void open(string user,string file,int attribute);void close(string user,string file);void  readfile(string user,string file);//直接覆盖void write(string user,string file,string in);void help();void readfile(string user,string file);void synFreePM();PM* getPM();FCB* getFile(string user,string name);UFD* getDIR(string user);void showFileContens(FCB*fcb);int main(){    initPM();    initSys();    string CMD[10]={"CREATE","DELETE","OPEN","CLOSE","READ","WRITE"};    int op=-1;    string cmd,user,fileName;    int fileType,attribute;    while(true)    {        op=-1;        cout<<"-----------input:USER CMD PARAMETERS ...  /?(for cmd help)/EXIT"\            "------------"<<endl;        cin>>cmd;        cout<<cmd<<endl;        if(cmd=="EXIT")          break;        else if(cmd=="?")        {            op=10;        }else        {            for(int i=0;i<10;i++)            {                if(cmd==CMD[i])                {                    op=i;                    break;                }            }        }        switch(op)        {            case 0://CREATE                cin>>user>>fileName>>fileType>>attribute;                create(user,fileName,fileType,attribute);                break;            case 1://DELETE                cin>>user>>fileName;                del(user,fileName);                break;            case 2://OPEN                cin>>user>>fileName>>attribute;                open(user,fileName,attribute);                break;            case 3://CLOSE                cin>>user>>fileName;                close(user,fileName);                break;            case 4://READ                cin>>user>>fileName;                readfile(user,fileName);                break;            case 5://WRITE                {                    //case 里边不能创建变量,可通过这样的方式解决 {}                    string tmp;                    cin>>user>>fileName>>tmp;                    cout<<user<<" "<<fileName<<" "<<tmp<<endl;                    write(user,fileName,tmp);                    break;                }            case 10:                help();                break;            default:                cout<<"input wrong,no this cmd"<<endl;        }        cout<<endl;    }    return 0;}void createUser(string name,string dir){    MFD user;    user.user=name;    user.ufd.name=dir;    user.ufd.status=0;    user.ufd.max_open_files=MAX_OPEN_FILE_USER;    user.ufd.num_open_files=0;    mfd.push_back(user);}void initSys(){    int count=0;    string user,dir;    cout<<"创建用户数"<<endl;    cin>>count;    cout<<"用户名\t根目录"<<endl;    for(int i=0;i<count;i++)    {        cin>>user>>dir;        cout<<user<<"\t"<<dir<<endl;        createUser(user,dir);    }}//分配物理块页面void initPM(int size){    cout<<"初始化物理块页面,页面大小:"<<size<<endl;    //每个块大小16    PM pm;    pm.len=size;    page=size;    pm.base=0;    pm.next=NULL;    pm.status=0;    int sum=MAX/16;    for(int i=0;i<sum;i++)    {        pm.base=i*size;        pmFree.push_back(pm);    }}PM* getPM(){    cout<<"--------pm-----------"<<endl;    PM *pm=NULL;    if(pmFree.size()>0)    {        PM tmp=*(pmFree.begin());        tmp.status=1;        cout<<"new applyed pm:"<<endl;        cout<<tmp.base<<"-"<<tmp.len<<endl<<endl;        pmFree.erase(pmFree.begin());        pmUsed.push_front(tmp);        pm=(PM*)&(pmUsed.begin()->base);    }    if(pm==NULL)        cout<<"apply dir error"<<endl<<endl;    return pm;}void  synFreePM(){    cout<<"---同步PM---"<<endl;    list<PM>::iterator it=pmUsed.begin();    for(;it!=pmUsed.end();it++)    {        if(it->status==0)        {            pmFree.push_back(*it);            it=pmUsed.erase(it);//注意这样更新it迭代器,否则会出错,具体原因查STL        }    }}UFD* getDIR(string user){    list<MFD>::iterator it;    for(it=mfd.begin();it!=mfd.end();it++)    {        if(it->user==user)        {            return &(it->ufd);        }    }    cout<<"apply dir error"<<endl;    return NULL;}FCB* getFile(string user,string file){    UFD*ufd=getDIR(user);    if(ufd==NULL)      return NULL;    list<FCB>::iterator it;    for(it=ufd->file.begin();it!=ufd->file.end();it++)    {        if(it->name==file)        {            return (FCB*)&(it->name);        }    }    cout<<"apply file error or file is creating which does not have file"<<endl;    //返回NULL表示当前为空或者不存在该文件    return NULL;}void showFiles(){    cout<<endl<<"-----files-----"<<endl;    list<MFD>::iterator it;    for(it=mfd.begin();it!=mfd.end();it++)    {        cout<<it->user<<"\t"<<it->ufd.name<<"\t"            <<"status:"<<it->ufd.file.size()<<endl;        cout<<"files:"<<endl;        if(it->ufd.file.size()==0)          cout<<"no_files"<<endl;        for(list<FCB>::iterator itf=it->ufd.file.begin();                    itf!=it->ufd.file.end();itf++)            cout<<itf->name<<endl;    }    cout<<endl;}void showFileContens(FCB*fcb){    cout<<endl<<"-----file_contents-----"<<endl;    cout<<"file:"<<fcb->name<<" contents:"<<endl;    PM*pm=fcb->next;    int count=0;    int lens=0;    int size=fcb->len;    for(int i=0,lens=0;i<fcb->len;i++,lens++)    {        if(pm==NULL)          break;        if(lens+1>=page)        {            pm=pm->next;            lens=0;        }        cout<<buf[pm->base+lens];        count++;    }    cout<<endl;    cout<<"file len:"<<fcb->len<<endl;    cout<<"used pm count:"<<count<<endl<<endl;}//模拟中目录只有一个//type:目录or 流文件 void create(string user,string file,int type,int attribute){    cout<<"-------create-------"<<endl;    PM *pm=getPM();    if(pm==NULL)      return;    UFD* ufd=getDIR(user);    if(ufd==NULL)        return;    FCB*fcb=getFile(user,file);    if(fcb!=NULL)//exits    {        cout<<file<<" already exits ->"            <<"rename to ";        file=file+"2";        cout<<file<<endl;    }    cout<<ufd->name<<endl;    FCB nfcb;    nfcb.name=file;    nfcb.len=0;    nfcb.attribute=attribute;    nfcb.next=pm;    //创建模式,表示此时可以对文件进行读写,而不管文件类型是否可写    nfcb.status=2;    ufd->file.push_back(nfcb);    pm->next==NULL;    pm->status=1;    showFiles();}void del(string user,string file){    cout<<"-------delete-------"<<endl;    UFD *ufd=getDIR(user);    if(ufd!=NULL)    {        list<FCB>::iterator it=ufd->file.begin();        for(;it!=ufd->file.end();it++)        {            if(it->name==file)            {                cout<<"find file:"<<it->name<<endl;                if(it->status>0)                {                    cout<<"delete error:"<<it->name<<" is using"<<endl;                }else if(it->status==0)                {                    PM*pm=it->next;                    while(pm!=NULL)                    {                        //统一更新删除,不在这一个一个的删                        pm->status=0;                        pm=pm->next;                    }                    it->next=NULL;                    cout<<"deleted file:"<<it->name<<endl;                    ufd->file.erase(it);                    break;                }            }        }    }    //同步PM list    synFreePM();    showFiles();}void open(string user,string file,int attribute){    cout<<"-------open-------"<<endl;    UFD *ufd=getDIR(user);    if(ufd==NULL)      return;    if(ufd->num_open_files+1>ufd->max_open_files)    {      cout<<"the num of openned files limits in"<<ufd->max_open_files<<endl;      return;    }    FCB*fcb=getFile(user,file);    if(fcb==NULL)      return;    if(fcb->status!=0&&fcb->status!=2)//0can use 2 new create -2 not exists 1 used    {        cout<<"this file cant use:"<<fcb->status<<endl;        return;    }    if(fcb->status==0)        fcb->status=1;    ufd->num_open_files++;    cout<<"open the file:"<<fcb->name<<endl;    showFiles();}void close(string user,string file){    cout<<"-------close-------"<<endl;    cout<<file<<endl;    FCB*fcb=getFile(user,file);    if(fcb==NULL)      return;    fcb->status=0;//将刚创建的文件状态设为正常    UFD *ufd=getDIR(user);    ufd->num_open_files--;}void  readfile(string user,string file){    cout<<"-------read-------"<<endl;    FCB*fcb=getFile(user,file);    if(fcb==NULL)      return;    if(fcb->status!=1&&fcb->status!=2)    {      cout<<"file is not openned for read"<<endl;      return;    }    if(fcb->attribute==2)    {        cout<<"error:"<<fcb->name<<" cannt be read"            <<endl<<"its attribute:"<<fcb->attribute<<endl;        return ;    }    showFileContens(fcb);}//仅追加模式void write(string user,string file,string in){    //不在对文件控制了    cout<<"-------write-------"<<endl;    FCB*fcb=getFile(user,file);    if(fcb==NULL)      return;    if(fcb->status!=1&&fcb->status!=2)    {      cout<<"file is not openned for write"<<endl;      return;    }    if(fcb->attribute!=1)    {        cout<<"error:"<<fcb->name<<" cannt be writed"            <<endl<<"its attribute:"<<fcb->attribute<<endl;        return;    }    int size=in.length();    //create时,分配了一个PM,当时不在那操作就好了,全部交到write操作    PM*pm=fcb->next;    int count=1;    if(pm==NULL)      cout<<"error:create 已经创建,但丢失"<<endl;    while(pm->next!=NULL)    {        count++;        pm=pm->next;    }    cout<<"last pm:"<<pm->base<<endl;    cout<<"file len:"<<fcb->len<<endl;    int begin=(count*page-fcb->len)%page;//page==pm->len    cout<<"base:"<<begin<<endl;    if(begin>=pm->len&&begin<0)    {       cout<<"error"<<endl;       return;    }    for(int i=0;i<size;i++)    {        if(begin>=pm->len)        {            pm->next=getPM();            if(pm==NULL)              return;            pm=pm->next;//在这被坑了,只考虑链接,忘了更新指针            begin=0;        }        buf[pm->base+begin++]=in.at(i);        fcb->len++;    }    showFileContens(fcb);}void help(){    cout<<"-------help-------"<<endl;    cout<<"CREATE username filename filetype(file or dir) attribute(r/w/e) "<<endl;    cout<<"DELETE username filename  "<<endl;    cout<<"OPEN username filename attribute"<<endl;    cout<<"CLOSE username filename"<<endl;    cout<<"WRITE username filename inputstring"<<endl;    cout<<"READ username filename"<<endl;}        ```- 测试数据```language3user1 root1user2 root2user3 root3?    CREATE user1 test1 0 0CREATE user1 test1 0 0CREATE user1 test2 0 0CREATE user1 test3 0 0OPEN user1 test1 1OPEN user1 test2 2OPEN user1 test3 3  //测试一个用户最多打开k个文件OPEN user1 test12 2WRITE user1 test1 12345678901234567890  //测试写入READ user1 test1  //测试读取DELETE user1 test1CLOSE user1 test1DELETE user1 test1CREATE user2 test2 0 1 //测试多用户OPEN user2 test2 1WRITE user2 test2 aaaaabbbbbdddddfffffREAD user2 test2CLOSE user2 test2EXIT
原创粉丝点击