实验八 虚拟内存系统的页面置换算法模拟

1、 实验目的

通过对页面、 页表、 地址转换和页面置换过程的模拟, 加深对虚拟页式内存管理系统的页面置换原理和实现过程的理解。

2、 实验基本知识及原理

需要调入新页面时, 选择内存中哪个物理页面被置换, 称为置换策略。 页面置换算法的目标:
把未来不再使用的或短期内较少使用的页面调出, 通常应在局部性原理指导下依据过去的统计数据进行预测, 减少缺页次数。
教材给出的常用的页面置换算法包括:
1) 最佳置换算法(OPT): 置换时淘汰“未来不再使用的”或“在离当前最远位置上出现的”页面。
2) 先进先出置换算法(FIFO): 置换时淘汰最先进入内存的页面, 即选择驻留在内存时间最长的页面被置换。
3) 最近最久未用置换算法(LRU): 置换时淘汰最近一段时间最久没有使用的页面, 即选择上次使用距当前最远的页面淘汰

3、 实验内容

(1)假设每个页面中可存放 10 条指令, 分配给一作业的内存块( 页框) 数为 4。
(2)用 C 语言模拟一作业的执行过程, 该作业共有 320 条指令, 即它的地址空间为 32 页, 目前它的所有页都还未调入内存。 在模拟过程中, 如果所访问的指令已在内存, 则显示其物理地址, 并转下一条指令。 如果所访问的指令还未装入内存, 则发生缺页, 此时须记录缺页的次数, 并将相应页调入内存;如果 4 个内存块中均已装入该作业, 则需进行页面置换;最后显示其物理地址, 并转下一条指令。 在所有 320 条指令执行完毕后, 请计算并显示作业运行过程中发生的缺页率。
(3)置换算法请分别考虑 OPT、 FIFO 和 LRU 算法。
(4) 测试用例(作业中指令序列)按下述原则生成:
通过随机数产生一个指令序列, 共 320 条指令。
① 50%的指令是顺序执行的;
② 25%的指令是均匀分布在前地址部分;
③ 25%的指令是均匀分布在后地址部分;
具体的实施方法是:
① 在[0, 319]的指令地址之间随机选取一起点 m;
② 顺序执行一条指令, 即执行地址为 m+1 的指令;
③ 在前地址[0, m+1]中随机选取一条指令并执行, 该指令的地址为 m1;
④ 顺序执行一条指令, 其地址为 m1+1;
⑤ 在后地址[m1+2, 319]中随机选取一条指令并执行;
⑥ 重复上述步骤①~⑤, 直到执行 320 条指令。
将指令序列变换为页地址流
假设: ① 页面大小为 1K; ② 用户内存容量为 4 页; ③用户虚存容量为 32K;
在用户虚存中, 按每 K 存放 10 条指令排列虚存地址, 即 320 条指令在虚存中的存放方式为:
第 0 条~第 9 条指令为第 0 页(对应虚存地址为[0,9]);
第 10 条~第 19 条指令为第 1 页(对应虚存地址为[10,19]);
……
第 310 条~第 319 条指令为第 31 页(对应虚存地址为[310,319]);
按以上方式, 用户指令可组成 32 页。

代码实现:

#include <iostream>
#include<bits/stdc++.h>
/*
2021-12-21 @浩茫
虚拟内存系统的页面置换算法
*/
using namespace std;
int a[320];//指令序列
int page[4]= {-1,-1,-1,-1}; //页框数组,-1代表为空
int page_num[4]; //记录每一页的次数
void creat_list()
{
    int m;
    int i,m1,m2;
    for(i=0; i<320;)
    {
        m =rand()%(320);
        //a[i]=m;
        //i++;//在[0, 319]的指令地址之间随机选取一起点 m
        a[i]=m+1;
        i++;//顺序执行一条指令, 即执行地址为 m+1 的指令;
        m1 = rand()%(m+2);
        a[i]=m1;
        i++;//在前地址[0, m+1]中随机选取一条指令并执行, 该指令的地址为 m1;
        a[i]=m1+1;
        i++;//顺序执行一条指令, 其地址为 m1+1;
        m2=m1+2+rand()%(320-m1-2);// 在后地址[m1+2, 319]中随机选取一条指令并执行;
        a[i]=m2;
        i++;
    }
}
int b[320];//每一条指令所在的页号
void show_page()
{
    int i;
    for(i=0; i<320; i++)
    {
        b[i]=a[i]/10;
    }
}
int void_page() //判断页框是否为空
{
    int i;
    for(i=0; i<4; i++)
    {
        if(page[i]==-1)return i;//返回页框号
    }
    return -1;//不为空
}
int jude(int a)//判断是否已经存在该页
{
    for(int i=0; i<4; i++)
    {
        if(page[i]==a)return i;//返回页框
    }
    return -1;//不存在
}
void OPT()
{
    int i,x;
    int dst_page=0;
    for(i=0; i<20; i++ )
    {
        if(jude(b[i])!=-1)//判断页框内是否已经存在该页
        {
            printf("第%d条指令%d已在内存中,物理位置:框%d+%d页内偏移\n",i+1,a[i],jude(b[i]),a[i]%10);
            printf("页框对应页号: %d\t%d\t%d\t%d\t\n\n",page[0],page[1],page[2],page[3],b[i]);
        }
        else
        {
            if(void_page()!=-1) //当页框存在空位时直接放入
            {
                x=void_page();
                page[x]=b[i];
                printf("第%d条指令%d不在内存中,将其放在:框%d+%d页内偏移\n",i+1,a[i],x,a[i]%10);
                printf("页框对应页号: %d\t%d\t%d\t%d\t\n\n",page[0],page[1],page[2],page[3],b[i]);
            }
            else//页框已满,进行页面置换
            {
                for(int j=0; j<4; j++)
                {
                    for(int k=i+1; k<320; k++)
                    {
                        if(page[j]==b[k])
                        {
                            page_num[j]=k-i;
                            break;
                        }
                    }
                }
                x=0;
                for(int j=0; j<4; j++)
                {
                    if(page_num[j]>x)
                    {
                        x=page_num[j];
                        dst_page = j ;
                    }
                }
                page[dst_page] = b[i];
                printf("第%d条指令%d不在内存中,页面置换 ",i+1,a[i]);
                printf(":框%d+%d页内偏移\n",dst_page,a[i]%10);
                printf("页框对应页号: %d\t%d\t%d\t%d\t\n\n",page[0],page[1],page[2],page[3],b[i]);
            }
        }
    }
}

void LRU()
{
    int i,x;
    int dst_page=0;
    for(i=0; i<20; i++ )
    {
        if(jude(b[i])!=-1)//判断页框内是否已经存在该页
        {
            printf("第%d条指令%d已在内存中,物理位置:框%d+%d页内偏移\n",i+1,a[i],jude(b[i]),a[i]%10);
            printf("页框对应页号: %d\t%d\t%d\t%d\t\n\n",page[0],page[1],page[2],page[3],b[i]);
        }
        else
        {
            if(void_page()!=-1) //当页框存在空位时直接放入
            {
                x=void_page();
                page[x]=b[i];
                printf("第%d条指令%d不在内存中,将其放在:框%d+%d页内偏移\n",i+1,a[i],x,a[i]%10);
                printf("页框对应页号: %d\t%d\t%d\t%d\t\n\n",page[0],page[1],page[2],page[3],b[i]);
            }
            else//页框已满,进行页面置换
            {
                for(int j=0; j<4; j++)
                {
                    for(int k=i-1; k>=0; k--)
                    {
                        if(page[j]==b[k])
                        {
                            page_num[j]=i-k;
                            break;
                        }
                    }
                }
                x=0;
                for(int j=0; j<4; j++)
                {
                    if(page_num[j]>x)
                    {
                        x=page_num[j];
                        dst_page = j ;
                    }
                }
                page[dst_page] = b[i];
                printf("第%d条指令%d不在内存中,页面置换 ",i+1,a[i]);
                printf(":框%d+%d页内偏移\n",dst_page,a[i]%10);
                printf("页框对应页号: %d\t%d\t%d\t%d\t\n\n",page[0],page[1],page[2],page[3],b[i]);
            }
        }
    }
}

void FIFO()
{
    int i,x;
    int dst_page=0;
    int counter=0;//置换标志位
    for(i=0; i<20; i++ )
    {
        if(jude(b[i])!=-1)//判断页框内是否已经存在该页
        {
            printf("第%d条指令%d已在内存中,物理位置:框%d+%d页内偏移\n",i+1,a[i],jude(b[i]),a[i]%10);
            printf("页框对应页号: %d\t%d\t%d\t%d\t\n\n",page[0],page[1],page[2],page[3],b[i]);
        }
        else
        {
            if(void_page()!=-1) //当页框存在空位时直接放入
            {
                x=void_page();
                page[x]=b[i];
                counter=(counter+1)%4;
                printf("第%d条指令%d不在内存中,将其放在:框%d+%d页内偏移\n",i+1,a[i],x,a[i]%10);
                printf("页框对应页号: %d\t%d\t%d\t%d\t\n\n",page[0],page[1],page[2],page[3],b[i]);
            }
            else//页框已满,进行页面置换
            {
                page[counter] = b[i];
                counter=(counter+1)%4;
                printf("第%d条指令%d不在内存中,页面置换 ",i+1,a[i]);
                printf(":框%d+%d页内偏移\n",dst_page,a[i]%10);
                printf("页框对应页号: %d\t%d\t%d\t%d\t\n\n",page[0],page[1],page[2],page[3],b[i]);
            }
        }
    }
}
int main()
{
    int i;
    int j;
    int n ;
    cout << "=====虚拟内存页面置换算法=====" << endl;
    cout<<"随机产生320条指令序列中......\n";
    creat_list();
    for(int i=0; i<320; i++)
    {
        printf("%-3d ",a[i]);
        if((i+1)%16==0)cout<<"\n";
    }
    cout<<"对应访问的页面为:\n";
    show_page();
    for(i=0; i<320; i++)
    {
        printf("%-2d  ",b[i]);
        if((i+1)%16==0)cout<<"\n";
    }
    while(true)
    {
        cout<<"\n选择你的算法:\n";
        cout<<"1、最佳置算法(OPT)\n";
        cout<<"2、先进先出置换算法(FIFO)\n";
        cout<<"3、最近最久未用置换算法(LRU)\n";
        cin>>n;
        if(n==-1)break;
        switch(n)
        {

        case 1:
            cout<<"最佳置算法(OPT)======\n";
            OPT();
            break;
        case 2:
            cout<<"先进先出置换算法(FIFO)======\n";
            FIFO();
            break;
        case 3:
            cout<<"最近最久未用置换算法(LRU)======\n";
            LRU();
            break;
        }
    }
    return 0;
}

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
(1)通过随机数产生一个指令序列,共320条指令。指令的地址按下述原则生成: ①、 50%的指令是顺序执行的; ②、 25%的指令是均匀分布在前地址部分; ③、 25%的指令是均匀分布在后地址部分。 具体的实施方法是: ① 在[0,319]的指令地址之间随机选取一起点m; ② 顺序 执行一条指令,即执行地址为m+1的指令; ③ 在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为m’; ④ 顺序执行一条指令,其地址为m’+1; ⑤ 在后地址[m’+2,319]中随机选取一条指令并执行; ⑥ 重复上述步骤,直至执行320次指令。 (2) 将指令序列变换成页地址流 设:①页面大小为1K; ②用户内存容量为4页到32页; ③用户虚存容量为32K; 在用户虚存中,按每K存放10条指令排列虚存地址,即320条指令在虚存中的存放方式为: 第0条~第9条指令为第0页(对应的虚存地址为[0,9]); 第10条~第19条指令为第1页(对应的虚存地址为[10,19]); . 第310条~第319条指令为第31页(对应的虚存地址为[310,319]); 按以上方式,用户指令可组成32页。 (3) 计算并输出下述各种算法在不同的内存容量下的命中率。 ① 先进先出的算法(FIFO); ② 最近最少使用算法(LRR); ③ 最佳淘汰法(OPT):先淘汰最不常用的页地址; ④ 最少访问页面算法(LFR); ⑤ 最近不经常使用算法(NUR)。 其中③和④为选择内容。 命中率=1-(页面失效次数)/(页地址流长度) 在本实验中,页地址流的长度为320,页面失效次数为每次访问相应指令时,该指令所对应的页不在内存的次数。
假设每个页面中可存放10条指令,分配给作业的内存块数为4。 用C语言语言模拟一个作业的执行过程,该作业共有320条指令, 即它的地址空间为32页,目前它的所有页都还未调入内存。在模拟过程中,如果所访问的指令已在内存,则显示其物理地址,并转下一条指令。如果所访问的指令还未装入内存,则发生缺页,此时需要记录缺页的次数,并将相应页调入内存。如果4个内存块均已装入该作业,则需要进行页面置换,最后显示其物理地址,并转向下一条指令。在所有320条指令执行完毕后,请计算并显示作业运行过程中发生的缺页率。 置换算法:请分别考虑最佳置换算法(OPT)、先进先出(FIFO)算法和最近最久未使用算法(LRU)。 作业中指令的访问次序按下述原则生成: 50%的指令是顺序执行的; 25%的指令是均匀分布在前地址部分; 25%的指令是均匀分布在后地址部分; 具体的实施方法是:    在[0,319]的指令地址之间随机选取一起点m;    顺序执行下一条指令,即执行地址序号为m+1的指令;    通过随机数,跳转到前地址部分[0,m+1]中的某条指令处,其序号为m1;    顺序执行下一条指令,其地址序号为m1+1的指令;    通过随机数,跳转到后地址部分[m1+2,319]中的某条指令处,其序号为m2;    顺序执行下一条指令,其地址序号为m2+1的指令; 重复跳转到前地址部分,顺序执行,跳转到后地址部分,顺序执行的过程直至执行320条指令。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浩茫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值