页式存储管理: 最佳置换(OPT)--先进先出页面置换(FIFO)--最久未使用置换(LRU)

实验题目

设计和实现最佳置换算法、先进先出置换算法、最近最久未使用置换算法、页面缓冲置换算法;通过页面访问序列随机发生器实现对上述算法的测试及性能比较。

实验要求

假设前提

  • 模拟的虚拟内存的地址为16位,页面大小为1K,模拟的物理内存有32K;
  • 页表用整数数组或结构数组来表示;
  • 页面访问序列串是一个整数序列,整数的取值范围为0到N - 1。页面访问序列串中的每个元素p表示对页面p的一次访问。

性能测评及问题说明
测试不同的页面访问序列及不同的虚拟内存尺寸,并从缺页率、算法开销等方面对各个算法进行比较。(同时请给出在给定页面访问序列的情况下,发生页面置换次数的平均值)

概要设计

3.1模块设计
在这里插入图片描述
总模块图
3.2功能
随机访问序列生成

  • 确定虚拟内存的尺寸N,工作集的起始位置p,工作集中包含的页数e,工作集移动率m(每处理m个页面访问则将起始位置p +1),以及一个范围在0和1之间的值t;
  • 生成m个取值范围在p和p + e间的随机数,并记录到页面访问序列串中;
  • 生成一个随机数r,0 ≤ r ≤ 1;
  • 如果r < t,则为p生成一个新值,否则p = (p + 1) mod N;
  • 如果想继续加大页面访问序列串的长度,请返回第2步,否则结束。

1、最佳置换算法OPT
选择永不使用或是在最长时间内不再被访问(即距现在最长时间才会被访问)的页面淘汰出内。
2、先进先出置换算法FIFO
选择最先进入内存即在内存驻留时间最久的页面换出到外存。
进程已调入内存的页面按进入先后次序链接成一个队列,并设置替换指针以指向最老页面。
3、最近最久未使用置换算法LRU
以“最近的过去”作为“最近的将来”的近似,选择最近一段时间最长时间未被访问的页面淘汰出内存。
4、改进型Clock置换算法CLO
① 从查寻指针当前位置起扫描内存分页循环队列,选择A=0且M=0的第一个页面淘汰;若未找到,转②

② 开始第二轮扫描,选择A=0且M=1的第一个页面淘汰,同时将经过的所有页面访问位置0;若不能找到,转①

详细设计

4.1程序流程
在这里插入图片描述
程序总流程图
在这里插入图片描述
先进先出页面置换算法流程图
在这里插入图片描述

最近久未使用置换算法流程图
在这里插入图片描述
最佳置换算法流程图
在这里插入图片描述
改进型Clock置换算法流程图

程序代码

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<time.h>
#define N 64   //虚拟内存大小
#define MAX 2000    //引用串的长度
#define P 32  //物理内存大小
 
using namespace std;
int result;  //置换次数
int RS[100] = {};  //RS串
int M[P] = {0};   // 物理内存大小
 
void PRS()
{
	int p = 1;//工作集的起始位置p
	int e = 40;//工作集中包含的页数e
	int m = 64;//工作集移动率m
	double t = 0.5;
	int judge = 1;
	int count = 0;
	double r;
	while(judge == 1)
	{
		srand((unsigned)time(NULL));
		for(int i = 0;i < m;i++)
		{
			RS[count] = rand()%e+p;
			count++;
		}
		r = (rand()%9+1)/10;
		if(r < t)
		{
			p = rand()%N+1;
		}
		else
		{
			p = (p+1)%N;
		}
		if(count >= MAX){
            printf("以下是生成的引用串:\n");
            for(int i = 0;i < count;i++)
            {
                printf("%d ",RS[i]);
            }
            printf("\n");
            break;
		}
	}
}
 
void print(int c)
{
	printf("以下为物理内存情况:\n");
	for(int i = 0;i < c;i++)
	{
		printf("%d ",M[i]);
	}
	printf("\nend**********************\n");
}
 
//判断物理内存是否已满
int full(int c,int j)
{
	int judge = 0;
	for(int i = 0;i < c;i++)
	{
		if(RS[j] == M[i])
		{
			judge = 1;
			break;
		}
	}
	if(!judge)
	{
		M[c] = RS[j];
		c++;
	}
	return c;
}
 
//判断是否为缺页
int lack(int c, int j)
{
	int judge = 0;
	for(int i = 0;i < c;i++)
	{
		if(RS[j] == M[i])
		{
			judge = 1;
			break;
		}
	}
	return judge;
}
 
 
//最佳置换算法
int OPT()
{
	result = 0;
	int count = 0;
	for(int j = 0;j < MAX;j++)
	{
		int judge = 0;
		if(count < P)
		{
			count = full(count,j);
		}
		else
		{
			int number;
			judge = lack(count,j);
			if(!judge)   //没有找到,需进行置换
			{
				result++;
				int s;  //用于存放没有找到的页面的数组下标
				for(int k = 0;k < count;k++)
				{
					number = -1;
					for(int i = j+1;i < MAX;i++)
					{
						if(M[k] == RS[i])
						{
							if(number < i)
							{
								number = i;
								s = k;
							}
							break;
						}
					}
					//没有找到,说明此页面不会再被使用,所以直接进行替换
					if(number == -1)
					{
						s = k;
						break;
					}
				}
				M[s] = RS[j];
			}
		}
	}
	return result;
}
 
//先进先出置换算法
int FIFO()
{
	result = 0;
	int p = 0;
	int count = 0;
	for(int j = 0;j < MAX;j++)
	{
		int judge = 0;
		if(count < P)
		{
			count = full(count,j);
		}
		else
		{
			//判断是否是缺页
			judge = lack(count,j);
			//是缺页,进行置换
			if(!judge)
			{
				result++;
				M[p] = RS[j];
				p = (p+1)%P;
			}
		}
	}
	return result;
}
 
//最近最久未使用置换算法
int LRU()
{
	result = 0;
	int a[P];  //辅组数组,队尾为最近访问页面
	int count = 0;
	for(int j = 0;j < MAX;j++)
	{
		int judge = 0;
		if(count < P)
		{
			for(int i = 0;i < count;i++)
			{
				if(RS[j] == M[i])
				{
					judge = 1;
					//将页面提到队尾
					int change = M[i];
					for(int k = i;k < count-1;k++)
					{
						a[k] = a[k+1];
					}
					a[count-1] = change;
 
					break;
				}
			}
			if(!judge)
			{
				a[count] = RS[j];
				M[count] = RS[j];
				count++;
			}
		}
		else
		{
			//判断是否是缺页
			for(int i = 0;i < count;i++)
			{
				if(RS[j] == M[i])
				{
					judge = 1;
					//将页面提到队首
					int change = M[i];
					for(int k = i;k < P-1;k++)
					{
						a[k] = a[k+1];
					}
					a[P-1] = change;
 
					break;
				}
			}
			//是缺页,进行置换
			if(!judge)
			{
				result++;
				for(int i = 0;i < P;i++)
				{
					if(a[0] == M[i])
					{
						M[i] = RS[j];
						for(int k = 0;k < P-1;k++)
						{
							a[k] = a[k+1];
						}
						a[P-1] = RS[j];
 
						break;
					}
				}
			}
		}
	}
	return result;
}
 
//Clock置换算法
int CLO()
{
	result = 0;
	int p = 0;
	int a[MAX];   //辅助数组
	int count = 0;
	for(int j = 0;j < MAX;j++)
	{
		int judge = 0;
		if(count < P)
		{
			for(int i = 0;i < count;i++)
			{
				if(M[i] == RS[j])
				{
					a[i] == 1;
					judge = 1;
					break;
				}
			}
			if(!judge)
			{
				a[count] = 1;
				M[count] = RS[j];
				count ++;
			}
		}
		else
		{
			for(int i = 0;i < count;i++)
			{
				if(M[i] == RS[j])
				{
					judge = 1;
					a[i] = 1;
					break;
				}
			}
			//是缺页,进行置换
			if(!judge)
			{
				result++;
				while(1)
				{
					if(a[p] == 1)
					{
						a[p] = 0;
						p = (p+1)%P;
					}
					else
					{
						a[p] = 1;
						M[p] = RS[j];
						p = (p+1)%P;
						break;
					}
				}
			}
		}
	}
	return result;
}
 
int main()
{
	int condition = 1;
	while(condition)
	{
		//先调用函数生成引用串
		PRS();
 
		//对于生成的引用串用各个算法进行效率的测试
		char a[4][30] = {"最佳置换算法","先进先出置换算法",\
					     "最近最久未使用置换算法","Clock置换算法"};
		int r[5];
		r[0] = OPT();
		r[1] = FIFO();
		r[2] = LRU();
		r[3] = CLO();
		printf("\n****************************\n");
		printf("最终结果:\n");
		for(int i = 0;i < 4;i++)
		{
		    double q=(float)r[i]/MAX;
			printf("%s置换次数:%d,缺页率:%.3f\n",a[i],r[i],q);
		}
		printf("1.继续;\n");
		printf("0.退出;\n");
		scanf("%d",&condition);
	}
	return 0;
}

运行结果及分析

在这里插入图片描述
虚拟内存64
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
请添加图片描述
以上原文链接:https://blog.csdn.net/qq_41839567/article/details/90638952
C语言实现页面置换 先进先出算法(FIFO)
https://www.yht7.com/news/128723
https://blog.csdn.net/qq_34777600/article/details/79508613
4.实例

  1. 通过随机数产生一个指令序列,共 320 条指令。其地址按下述原则生成:
    (1)50%的指令是顺序执行的;
    (2)50%的指令是均匀分布在前地址部分;
    (3)50%的指令是均匀分布在后地址部分;
    具体的实施方法是:
    A. 在[0,319]的指令地址之间随机选取一起点 M;
    B. 顺序执行一条指令,即执行地址为 M+1 的指令;
    C. 在前地址[0,M+1]中随机选取一条指令并执行,该指令的地址为 M’;
    D. 顺序执行一条指令,其地址为 M’+1;
    E. 在后地址[M’+2,319]中随机选取一条指令并执行;
    F. 重复A—E,直到执行 320 次指令。
  2. 指令序列变换成页地址流 设 :
    (1)页面大小为1K;
    (2) 用户内存容量为 4 页到 32 页;
    (3)用户虚存容量为 32K。
    在用户虚存中,按每页存放10 条指令排列虚存地址,即 320 条指令在虚存中的存放方式为:
    第0条—第9条指令为第0页(对应虚存地址为[0,9]) ;
    第10条—第19条指令为第1页(对应虚存地址为[10,19]) ;
    ……………………
    第310条—第319条指令为第31页(对应虚存地址为[310,319]) ;按以上方式,用户指令可组成 32 页。
  3. 计算并输出下述各种算法在不同内存容量下的命中率。
    A. 先进先出(FIFO)页面置换算法
    B. 最近最久未使用(LRU)页面置换算法–最近最少使用算法
    C. 最佳(Optimal)页面置换算法

5.代码

#include<iostream>
#include<stdlib.h>
#include<iomanip>
#include<queue>
#include<string>
#include<time.h>
using namespace std;
#define max 0x3f3f3f3f
 
int size;
double ratio;
 
struct Order
{
    int id;       //序列号
    int numpage;  //属于页面号
};
Order order[320]; 
 
struct Page
{
    int num;
    bool in;      //是否在内存中
    int time;     //时间
};
Page page[32];
 
void init0()
{
    int first;
    srand((unsigned)time(NULL));  //随机种子
    for(int i=0;i<320;i+=6)
    {
        first=(int)(319.0*rand()/RAND_MAX)+1;
        order[i].id=first;              //任选一指令节点
        order[i+1].id=order[i].id+1;    //顺序访问下一条指令
        order[i+2].id=(int)(1.0*order[i].id*rand()/RAND_MAX); //前地址指令
        order[i+3].id=order[i+2].id+1;    //顺序访问下一条指令
        order[i+4].id=(int)(1.0*rand()*(318-order[i+2].id)/RAND_MAX)+order[i+2].id+2;   //后地址指令
        order[i+5].id=order[i+4].id+1;  //顺序访问下一条指令 
    }
}
 
void init()
{
    for(int i=0;i<320;i++)
    {
        order[i].numpage=order[i].id/10;
      //  cout<<i<<"  "<<order[i].id<<" page-> "<<order[i].numpage<<endl;
    }
    for(int i=0;i<32;i++)
    {
        page[i].in=0;
        page[i].num=i;
        page[i].time=max-1;
    }
}
 
void Fifo()
{
 
    int clock=1;        //记录时间
    double totalnum=0;     //指令不在内存的次数
    for(int i=0;i<320;i++)
    {
        int numin=0;
        for(int k=0;k<32;k++) 
        {
            if(page[k].in) numin++;
        }
        if(page[order[i].numpage].in==1) continue;   //指令所在页在内存中
        if(page[order[i].numpage].in==0)             //指令所在页不在内存中
        {
            if(numin<size)
            {
                totalnum++;     //缺页发生,加入内存
                page[order[i].numpage].in=1;
                page[order[i].numpage].time=clock;
                clock++;
          //      cout<<"进入 "<<order[i].numpage<<endl;
            }
            else
            {
                int Max=max;
                int kk;
                for(int k=0;k<32;k++)
                {
                    if(page[k].in&&page[k].time<Max)
                    {
                        Max=page[k].time;
                        kk=k;
                    } 
                }
                page[kk].in=0;
           //     cout<<"退出 "<<kk<<endl;
 
                totalnum++;     //缺页发生,加入内存
                page[order[i].numpage].in=1;
                page[order[i].numpage].time=clock;
                clock++;
            //    cout<<"进入 "<<order[i].numpage<<endl;
            }
        }
    }
    ratio=1-(totalnum/320.0);
    cout<<"失效次数: "<<totalnum<<endl;
    cout<<"命中率: "<<(int)(ratio*100)<<"%"<<endl;
 
}
 
void Lru()
{
    int clock=1;        //记录时间
    double totalnum=0;     //指令不在内存的次数
    for(int i=0;i<320;i++)
    {
        int numin=0;
        for(int k=0;k<32;k++) 
        {
            if(page[k].in) numin++;
        }
        if(page[order[i].numpage].in==1)             //指令所在页在内存中
        {
            page[order[i].numpage].time=clock;       //更新进入时间
            clock++;                       
        }
        if(page[order[i].numpage].in==0)             //指令所在页不在内存中
        {
            if(numin<size)
            {
                totalnum++;     //缺页发生,加入内存
                page[order[i].numpage].in=1;
                page[order[i].numpage].time=clock;
                clock++;
          //      cout<<"进入 "<<order[i].numpage<<endl;
            }
            else
            {
                int Max=max;
                int kk;
                for(int k=0;k<32;k++)
                {
                    if(page[k].in&&page[k].time<Max)
                    {
                        Max=page[k].time;
                        kk=k;
                    } 
                }
                page[kk].in=0;
           //     cout<<"退出 "<<kk<<endl;
 
                totalnum++;     //缺页发生,加入内存
                page[order[i].numpage].in=1;
                page[order[i].numpage].time=clock;
                clock++;
            //    cout<<"进入 "<<order[i].numpage<<endl;
            }
        }
    }
    ratio=1-(totalnum/320.0);
    cout<<"失效次数: "<<totalnum<<endl;
    cout<<"命中率: "<<(int)(ratio*100)<<"%"<<endl;
 
}
 
void Opt()
{
    int clock=1;        //记录时间
    double totalnum=0;     //指令不在内存的次数
    for(int i=0;i<320;i++)
    {
        int numin=0;
        for(int k=0;k<32;k++) 
        {
            if(page[k].in) numin++;
        }
        if(page[order[i].numpage].in==1)             //指令所在页在内存中
        {
            page[order[i].numpage].time=clock;       //更新进入时间
        }
        if(page[order[i].numpage].in==0)             //指令所在页不在内存中
        {
            if(numin<size)
            {
                totalnum++;     //缺页发生,加入内存
                page[order[i].numpage].in=1;
          //      cout<<"进入 "<<order[i].numpage<<endl;
            }
            else
            {
                bool n=false;
                int j,kk;
                for(int k=0;k<32;k++)      //以后不使用
                {
                    if(page[k].in==1)
                    {
                        for(j=i+1;j<320;j++)
                        {
                            if(order[j].numpage==page[k].num)
                            {
                                break;
                            }
                        }
                        if(j==320) 
                        {
                            kk=k;
                            n=true;
                            break;
                        }
                    }
                }
                if(n) 
                {
                    page[kk].in=0; 
                    //   cout<<"退出 "<<kk<<endl;
                    totalnum++;     //缺页发生,加入内存
                    page[order[i].numpage].in=1;
                    //    cout<<"进入 "<<order[i].numpage<<endl;
                    continue;
                }
                for(int k=0;k<32;k++)      //最长时间以后才会使用
                {
                    if(page[k].in==1)
                    {
                        for(j=i+1;j<320;j++)
                        {
                            if(order[j].numpage==page[k].num)
                            {
                                if(page[k].time<=j)
                                {
                                    page[k].time=j;
                                }
                            }
                        }
 
                    }
                }
                int min=0; 
                for(int k=0;k<32;k++)
                {
                    if(page[k].in==1&&page[k].time>min)
                    {
                        kk=k;
                        min=page[k].time;
                    }
                }
                page[kk].in=0; 
           //   cout<<"退出 "<<kk<<endl;
                totalnum++;     //缺页发生,加入内存
                page[order[i].numpage].in=1;
            //    cout<<"进入 "<<order[i].numpage<<endl;
            }
        }
    }
    ratio=1-(totalnum/320.0);
    cout<<"失效次数: "<<totalnum<<endl;
    cout<<"命中率: "<<(int)(ratio*100)<<"%"<<endl;
 
}
 
int main(int argc,char* argv[])
{
    init0();
    for(int kkk=0;kkk<10;kkk++)
    {
        cout<<"**********************************"<<endl;
        while(1)
        {
            cout<<" 请输入内存容量(4-32):";
            cin>>size;
            if(size>=4&&size<=32) break;
            else cout<<"请正确输入内存容量!"<<endl;
        }
 
        cout<<endl;
        init(); 
        cout<<"先进先出(FIFO)算法: "<<endl;
        Fifo();
 
        cout<<endl;
        init();
        cout<<"最近最久未使用(LRU)算法: "<<endl;
        Lru();
 
        cout<<endl;
        init();
        cout<<"最佳(Optimal)页面置换算法: "<<endl;
        Opt();
        cout<<"**********************************"<<endl;
    }
    return 0;
}

运行结果
在这里插入图片描述

  • 12
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值