• 操作系统作业~分页式存储管理(作业)


    1、 实现分页式存储管理地址转换过程,将逻辑地址转换成物理地址。

    2、 在此基础上实现请求分页的地址转换;实现请求页式地址转换中出现的缺页现象中,用到的先进先出、最近最久未使用、最佳置换算法。掌握内存的分配方法和虚拟存储器的概念和原理。

    利用键盘输入本模拟系统分配给作业的内存物理块个数,作业在执行过程中的页面调度次序。计算出三种算法的缺页次数和缺页率。

    先说下什么是页(页面):就是将用户的程序的的地址空间分成固定大小的区域,称为”页“,或者”页面“

    之后将这些页离散的放进内存中,这样解决了内存的碎片问题

    记得老师上课说了下这两个概念不能混,现在区分下:

    在第4章存储器管理,学习了分页式存储管理方式(是为了解决内存的碎片问题)

    在第5章虚拟存储器,学习了请求分页式管理方式(除了解决碎片问题外,又“扩充”了内存的大小(虚拟))

    在这里为了使得固定数目的内存来运行较多的进程,增加了调页功能和页面置换功能。

    页面置换用到了三种方法

    1.先进先出(FIFO),最先得到内存的最先置换它    

     2最近最久未使用(LRU),和FIFO差不多,只是把命中的页面放在最不应该淘汰的位置(栈顶,或者栈低,不同的老师有不同的讲法),就是说新来的将最晚被淘汰  

     3最佳置换方法,这个只是用来评估的算法,它要预测将来谁是最迟要内存的(因为它目前不用内存,先让别人用内存),把它先淘汰。

    下面是流程图,你们不要嫌弃我~我真不会把流程图插进来,只好截图了(可是本姑娘已经对齐了~)

    再下面是代码~你们知道怎么插入代码么~为啥我的那么难看

    写代码的过程中有几个问题,我在下面用黄色笔标注出来!编译器vs2010

    有一些全局变量是想到啥就直接加的,你们看起看可能也会非常费劲。主要注意思想,看别人代码是个超级烦的事情。我很少很少很少看别人写的代码

    所以我觉得我写代码就非常罗嗦,一点不简洁。这个是我第一次发这个东西,我以后写的时候尽可能注意简洁性。

    你们要是有不懂的就在下面问吧~

     

     

    #include<iostream>
    #include<vector>
    #include<string>
    using namespace std;

    typedef struct Pagetable
    {
    int physicalblock_No;//物理块号
    int state;//状态位
    }PT;
    typedef struct Pagetable3
    {
    int physicalblock_No3;//物理块号
    int state3;//状态位
    }PT3;
    int fifo;
    int lru;
    int opti;
    int opt[25];//保存出现过的页号
    int h=0;
    PT pt[100];
    PT3 pt3[100];
    int COUNT;
    vector<int> stack;//FIFO栈
    vector<int> stack2;//LRU栈
    vector<int> stack3;//optimal栈
    int physical_block;//内存块数
    int page_size;//页大小
    int pagetable_len;//页表长度
    int m[8][8];//位示图
    int PageAdd;//页内地址
    void Inite();//初始化位示图
    void showwst();//显示位视图
    void showqyl();//显示缺页率
    int call_in();//调入页面
    void LRU(int page_no);//
    void FIFO(int page_no);//
    void optimal(int pageno);
    void showstack();//显示栈
    void showstack2();//LRU
    void showstack3();//opti
    int w;
    void main()
    {
    Inite();
    int logic_add;
    cout<<"输入所分配的内存块数";
    cin>>physical_block;
    int a;
    cout<<"输入页面大小(kb)";
    cin>>page_size;
    cout<<"输入页表长度";
    cin>>pagetable_len;
    int i;
    for(int i=0;i<pagetable_len;i++)//最开始页表的状态位都是0
    {
    pt[i].state=0;
    }
    int PageNo;
    int count=0;
    do{
    COUNT++;
    do
    {
    a=0;
    cout<<"输入逻辑地址";
    count=count+1;
    cin>>hex>>logic_add;//我在这里是以16进制的方式输入的地址,在下面的所有代码却都默认为16进制了!!!!!为何啊?
    PageNo=logic_add/(1024*page_size);//页号

    if(PageNo>=pagetable_len)
    {
    a=1;
    cout<<"越界中断请重新输入"<<endl;
    }

    }while(a==1);

    cout<<"页号"<<PageNo<<endl;
    opt[h]=PageNo;
    h++;
    PageAdd=logic_add%(1024*page_size);//页内地址
    cout<<"页内地址"<<hex<<PageAdd<<endl;
    /*if(pt[PageNo].state==0)
    {
    cout<<"此页不在内存!正在查找是否有剩余物理块......"<<endl;
    }*/
    if(stack.size()==physical_block)//栈满了
    {
    cout<<"FIFO"<<endl;
    FIFO(PageNo);
    cout<<"LRU"<<endl;
    LRU(PageNo);

    }
    else//栈没满
    {
    int n=0;
    for(int i=0;i<stack.size();i++)
    {
    if(stack[i]==PageNo)
    {
    cout<<"命中"<<endl;
    cout<<"物理地址"<<endl<<hex<<pt[PageNo].physicalblock_No*1024+PageAdd;
    n=1;
    break;
    }
    }
    if(n==0)
    {
    cout<<"内存有剩余,可以从位示图中分配内存(物理块号)"<<endl;
    int local=call_in();//
    pt[PageNo].physicalblock_No=local;//页表
    cout<<"物理地址"<<endl;
    cout<<hex<<local*page_size*1024+PageAdd<<endl;
    stack.push_back(PageNo);
    stack2.push_back(PageNo);
    stack3.push_back(PageNo);
    cout<<"FIFO"<<endl;
    showstack();
    cout<<"LRU"<<endl;
    showstack2();
    cout<<"最佳置换"<<endl;
    showstack3();
    pt[PageNo].physicalblock_No=local;
    pt[PageNo].state=1;
    pt3[PageNo].physicalblock_No3=local;
    pt3[PageNo].state3=1;
    }
    }
    cout<<"是否继续输入 1是 2否"<<endl;
    cin>>i;
    }while(i!=2);

    cout<<"最佳置换"<<endl;
    for(w=physical_block;w<COUNT;w++)
    {
    optimal(opt[w]);
    }
    showqyl();
    system("pause");
    }
    void showqyl()
    {//这个代码,就是我刚才说的默认为16进制,害得我必须加上dec(10进制输出)
    cout<<"FIFO"<<"缺页率:"<<dec<<fifo+physical_block<<"/"<<dec<<COUNT<<endl;
    cout<<"LRU"<<"缺页率:"<<dec<<lru+physical_block<<"/"<<dec<<COUNT<<endl;
    cout<<"optimal"<<"缺页率"<<dec<<opti+physical_block<<"/"<<dec<<COUNT<<endl;
    }
    int call_in()//位视图是8*8的
    {
    int loc;
    for(int h=2;h<8;h++)
    for(int lie=0;lie<8;lie++)
    {
    if(m[h][lie]==0)
    {
    loc=(((8*h)+lie)+1);
    cout<<dec<<loc<<"号内存可以分配"<<endl;
    m[h][lie]=1;
    h=8;
    break;

    }
    }
    showwst();
    return loc;
    }
    void Inite()
    {

    int h=2;
    for(int i=0;i<2;i++)//给最开始的前2行赋值为1,系统区
    {
    for(int j=0;j<8;j++)
    {
    m[i][j]=1;
    }
    }
    do{
    int a[32];
    int i=0;
    long num;
    num=rand()%128;

    //我在想各种方式变成2进制,什么atoi  itoa  各应死了,都不如自己写一个进制转换
    while(num>=1)//算出2进制数
    {
    a[i]=num%2;
    num=num/2;
    i++;
    }

    //不足8位在前面补0
    if(i<8)
    {
    for(int j=i;j<=7;j++)
    {
    a[j]=0;
    }
    }

    for(i=7;i>=0;i--)
    {
    m[h][i]=a[i];
    }
    h++;
    }while(h<8);

    for(int h=0;h<8;h++)//行
    {
    for(int l=0;l<8;l++)//列
    {
    cout<<m[h][l];
    }
    cout<<endl;
    }
    }

    void FIFO(int page_no)
    {
    int a=0;
    for(vector<int>::iterator it = stack.begin();it!=stack.end();++it)
    {
    if(page_no==*it)
    {
    cout<<"命中"<<endl;
    cout<<"物理地址"<<endl<<hex<<pt[page_no].physicalblock_No*1024*page_size+PageAdd<<endl;
    a=1;
    break;
    }
    }
    if(a==0)
    {
    fifo++;
    vector<int>::iterator it = stack.begin();
    pt[page_no].physicalblock_No=pt[*it].physicalblock_No;
    cout<<"物理地址"<<endl;
    cout<<hex<<pt[page_no].physicalblock_No*page_size*1024+PageAdd<<endl;
    stack.erase(it);
    stack.push_back(page_no);
    pt[page_no].state=0;
    }
    showstack();
    }
    void showstack()
    {

    for(int i=stack.size()-1;i>=0;i--)
    {
    cout<<stack[i]<<endl;
    }
    cout<<endl;

    }
    void showstack2()
    {

    for(int i=stack2.size()-1;i>=0;i--)
    {
    cout<<stack2[i]<<endl;
    }
    cout<<endl;
    }
    void showstack3()
    {
    for(int i=stack3.size()-1;i>=0;i--)
    {
    cout<<stack3[i]<<endl;
    }
    cout<<endl;
    }

    void LRU(int page_no)
    {
    int a=0;
    for(vector<int>::iterator it = stack2.begin();it!=stack2.end();++it)
    {
    if(page_no==*it)
    {

    cout<<"命中"<<endl;
    cout<<"物理地址"<<endl<<hex<<pt[page_no].physicalblock_No*1024*page_size+PageAdd<<endl;
    vector<int>::iterator it = stack2.begin();
    stack2.erase(it);
    stack2.push_back(page_no);
    a=1;
    break;
    }
    }
    if(a==0)
    {
    lru++;
    vector<int>::iterator it = stack2.begin();
    pt[page_no].physicalblock_No=pt[*it].physicalblock_No;
    cout<<"物理地址"<<endl;
    cout<<hex<<pt[page_no].physicalblock_No*page_size*1024+PageAdd<<endl;

    stack2.erase(it);
    stack2.push_back(page_no);

    }
    showstack2();
    }
    void showwst()
    {
    for(int h=0;h<8;h++)//行
    {
    for(int l=0;l<8;l++)//列
    {
    cout<<m[h][l];
    }
    cout<<endl;
    }
    }

    void optimal(int pageno)
    {
    int j=0;int a[25];int m=0;int flag=0;
    for(int i=0;i<physical_block;i++)
    {
    if(stack3[i]==pageno)
    {
    cout<<"命中"<<endl;
    cout<<"物理地址"<<endl<<hex<<pt3[pageno].physicalblock_No3*1024*page_size+PageAdd<<endl;
    m=1;
    break;

    }
    }
    if(m==0)
    {
    int p;
    opti++;//缺页次数
    while(j<physical_block)
    {
    for(p=w+1;p<h;p++)//w为当前缺页位置位置的下一个
    {
    if(stack3[j]==opt[p])//2==2
    {
    a[stack3[j]]=p;//,a这个数组存的是页面是在第几次出现的,a[2]=9 表示2页在第9个出现的,a[6]=8;代表6这个页面是在第8次出现的,那么淘汰2这个页面
    break;//写到这里我忽然想到了一个排序,计数排序,我不知道我为何会联想到这个伟大的算法
    }
    }
    if(p==h)
    {
    //此页面以后都不会被使用
    pt3[opt[w]].physicalblock_No3=pt3[stack3[j]].physicalblock_No3;
    stack3[j]=opt[w];

    cout<<"物理地址"<<endl;
    cout<<hex<<pt3[opt[w]].physicalblock_No3*page_size*1024+PageAdd<<endl;
    flag=1;
    j=physical_block;

    }
    j++;
    }
    if(flag==0)
    {
    int max=0;int out;//要淘汰的页号
    for(int i=0;i<20;i++)
    {
    if(a[i]>max)
    {
    out=i;
    max=a[i];
    }
    }
    for(int i=0;i<physical_block;i++)
    {
    if(stack3[i]==out)
    {
    pt3[pageno].physicalblock_No3=pt3[out].physicalblock_No3;
    cout<<"物理地址"<<endl;
    cout<<hex<<pt3[pageno].physicalblock_No3*page_size*1024+PageAdd<<endl;
    stack3[i]=pageno;
    }
    }
    }
    }
    showstack3();
    }

  • 相关阅读:
    MySQL 抓包工具
    php安全配置记录和常见错误梳理
    Mongodb副本集+分片集群环境部署记录
    线上mongodb 数据库用户到期时间修改的操作记录
    Redis+TwemProxy(nutcracker)集群方案部署记录
    Linux下Redis主从复制以及SSDB主主复制环境部署记录
    以多个实例方式打开Notepad++
    什么才是程序员的核心竞争力?zz
    谈谈如何在面试中发掘程序猿的核心竞争力zz
    解决Android SDK Manager更新时出现问题
  • 原文地址:https://www.cnblogs.com/ldphoebe/p/4852113.html
Copyright © 2020-2023  润新知