操作系统页面置换

页面置换算法


在这里插入图片描述
在这里插入图片描述
易混淆词:reg(寄存器)、block/PBC(分配的物理块)、page_num/PAC(页面序列)、memory【】(页号)、count / lps/exchange_numbber(缺页次数)、table/rel【】【】(矩阵)、lpp/lack_page_rate(缺页率)、index(页面号索引)、

OPT

所选择的被换出的页面将是最长时间内不再被访问,通常可以保证获得最低的缺页率

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

int toNextPageLen[50];
//当前页面位置下一次被访问的位置,下标为当前页面位置,值为下一次访问位置 

void OPT(int page_access[],int PBC,int PAC,int result[][50]){
	int k = 0;
	int nextPageAccessIndex[50];
//存储当前页面的位置,作为该页面上一次被访问的下一次访问位置 ,下标为页   面,值为下一次访问位置 
	memset(nextPageAccessIndex,0,sizeof(nextPageAccessIndex));
//初始化为0,代表没再访问过 
//1.获取当前位置页面下次访问该页面的位置 
	for(int i = PAC-1; i>=0; i--){
		int nextIndex = nextPageAccessIndex[page_access[i]]; 
		if(nextIndex <= 0){                        //没在访问过则位置设为无穷 
			toNextPageLen[i] = INT_MAX;
		}else{
			toNextPageLen[i] =  nextIndex;
		}
		nextPageAccessIndex[page_access[i]] = i;
	}
	
//2.计算每一次访问的每个物理块存放的当前页面 
	int flagBlock[50];
	//存储页面是否在物理块中,用于去重,下标为页面,值为访问位置 
	memset(flagBlock,-1,sizeof(flagBlock));//不存在物理块中为-1 
	for(int i = 0 ; i < PAC; i++){             //遍历访问位置 
		int len = 0;//存储下一次访问该页的最大长度 
		int block = -1;//要替换的物理块中页面 
		
		if(flagBlock[page_access[i]]!=-1){//如果存在物理块中,直接复制前一次数据 
			for(int j = 0; j < k; j++){
				result[j][i] = result[j][i-1];
			}
			flagBlock[page_access[i]] = i; 
			continue;
		}
		for(int j = 0; j < PBC; j++){         //遍历物理块 
			if(k < PBC){//如果当前使用的物理块数少于总共物理块数,复制上一次访问页面,在剩下的物理块中添加当前页面 
				if(j == k){                  //如果为新的物理块,直接存储当前页面 
					result[k][i] = page_access[i];//存储当前页面 
					flagBlock[page_access[i]] = i;// 标记为存在物理块中 
					k++; //使用的物理块数+1
					result[PBC][i] = 1;  //判断是否缺页,有增加则缺页 
					break;
				}else{//复制上一次的页面 
					result[j][i] = result[j][i-1];
				}
			}else{//如果物理块满 
				result[j][i] = result[j][i-1];//复制上一次页面 
				int s = toNextPageLen[flagBlock[result[j][i-1]]]-i;
			
				if(len < s){//找到下次访问最长页面替换 ,即判断物理块中页面 上次的下标 的下一次访问位置减去当前位置,得到距离长度 
					block = j;
					len = s;
				}
			}
		}
		if(block!=-1){
			flagBlock[result[block][i]] = -1;
			flagBlock[page_access[i]] = i;
			result[block][i] = page_access[i];//替换下次访问最长的页面 
			result[PBC][i] = 1;
		}
	}
}
int main(){
	int PBC;//物理块数 physical block count 
	int PAC;//页面访问次数 Page access count 
	int page_access[50];//存储访问的页面,下标代表第几次访问 
	int result[50][50];//0~PBC-1行0~PAC-1列代表每个物理块存储每次访问的页面,PBC行存储是否缺页,是为1,否为0 
	memset(result, -1, sizeof(result)); 
	printf("请输入物理块数:"); 
	scanf("%d",&PBC);
	printf("请输入访问次数:"); 
	scanf("%d",&PAC);
	for(int i = 0 ; i < PAC; i++){
		printf("请输入第%d次访问的页面:",i+1);
		scanf("%d",&page_access[i]); 
	}
	
	//OPT 
	OPT(page_access, PBC, PAC, result);
	
	//输出 
	printf("\n\n页面访问\t");
	for(int i = 0 ; i < PAC; i++){
		printf("%d\t",page_access[i]);
	}
	printf("\n");
	for(int i = 0; i < PBC; i++){
		printf("物理块%d\t\t",i+1);
		for(int j = 0; j < PAC; j++){
			if(result[i][j]!=-1&&result[PBC][j]!=-1){
				printf("%d\t",result[i][j]);
			}else{
				printf("\t");
			}
		}
		printf("\n");
	}
	int lack_page_number = 0;//缺页次数 
	printf("是否缺页\t");
	for(int i = 0; i < PAC; i++){
		printf("%c\t",result[PBC][i]==1?'Y':'N');
		if(result[PBC][i]==1)lack_page_number++;
	} 
	printf("\n"); 
	
	int exchange_numbber = lack_page_number - PBC;
	double lack_page_rate = lack_page_number/(double)PAC;
	printf("缺页次数: %d\n", lack_page_number);
	printf("置换次数: %d\n",exchange_numbber);
	printf("缺页率: %0.2lf%%\n",lack_page_rate) ;

}

在这里插入图片描述

在这里插入图片描述

FIFO

选择换出的页面是最先进入的页面。

该算法会将那些经常被访问的页面也被换出,从而使缺页率升高。
在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
#define PAGES 12  /*页面引用页数*/
#define M 4      /*当前分配给改作业的物理块数*/

/*页面引用串*/
int  page[PAGES] =  {1,2,3,4,5,1,4,1,2,3,4,5};
int  rel[M][PAGES];    /*存储结果数组*/
/*内存物理块结构体*/
typedef  struct {
   int  pnum;      /*该块中所存的页面号*/
   int  tm ;        /*从最近一次调入所经历的时间*/
}PBlock;
/*初始化物理块数组*/
void  init(PBlock *pb)
{
   int  i,j;
   //pb = (PBlock*)malloc(sizeof(PBlock)*M);
   for (i=0;i<M;i++){
     pb[i].pnum = -1;
     pb[i]. tm  = -1;
     for (j=0;j<PAGES;j++){
       rel[i][j] = -1;
     }
   }
}
/*打印结果数组*/
void  printRelArr( int  rel[M][PAGES])
{
   int  i,j;
   for (i=0;i<M;i++){
     for (j=0;j<PAGES;j++){
       if (rel[i][j]==-1)
         printf ( "-1" );
       else
         printf ( "%d " ,rel[i][j]);
     }
     printf ( "\n" );
   }
}
/*打印一维数组*/
void  printArr1( int  *arr, int  n)
{
     int  i;
     for (i=0;i<n;i++){
       printf ( "%d " ,arr[i]);
     }
     printf ( "\n" );
}
/*查看页面号为num的页面是否在内存块中,存在返回1*/
int  in_mem( int  num,PBlock *pb, int  m)
{
   int  i;
   int  b = 0;
   for (i=0;i<m;i++){
       if (pb[i].pnum == num){
         b = 1;
         break ;
       }
   }
   return  b;
}
int fifo(PBlock* pb, int m)
{
    int lps = 0;   /*缺页次数*/
    double lpp;   /*缺页率*/
    int p = 0;    /*替换指针*/
    int index = 0;  /*页面号索引*/
    while (index < PAGES) {
        if (!in_mem(page[index], pb, M)) {    //如果该页面不在物理块中
            pb[p].pnum = page[index];        /*将该页面放入物理块中*/
            p = (p + 1) % M;                     /*替换指针移动*/
            lps++;                           /*缺页次数加 1*/
            for (int i = 0; i < M; i++) {
                rel[i][index] = pb[i].pnum;
            }
        }
        index++;
    }
    printf("FIFO算法所得缺页次数为 %d\n", lps);
    lpp = (double)lps / PAGES;
    printf("FIFO算法缺页率为 %0.4lf \n", lpp);
    printf("页面号序列为:\n");
    printArr1(page, PAGES);
    printf("结果数列为:\n");
    printRelArr(rel);
    return 0;
}
int  main()
{
     //printArr(rel);
   PBlock pb[M];
   init(pb);
   fifo(pb,M);
   init(pb);
   return  0;
}

LRU

虽然无法知道将来要使用的页面情况,但是可以知道过去使用页面的情况。LRU 将最近最久未使用的页面换出

#include<stdio.h>
 
int block_num;   /*分配的物理块数*/
int page_num;   /*要访问的页面序列个数*/
int page[100]; /*要访问的页面序列*/
int memory[10]; /*物理块中的页号*/
int table[100][10]; /*显示矩阵*/
int reg[10];  /*寄存器--记录页面的访问时间*/
char Que[100];  /*数组,记录是否缺页*/
 

int main()
{	
    int count=0; /*记录缺页次数*/    
    int i,j,k;
 
	printf("|               LRU页面置换算法          |\n");
	
	while(1) 
	{
		printf("请输入分配的物理块的个数(M<=10):\n");
		scanf("%d",&block_num);
		if(block_num>10)
			printf("请重新输入"); 
		printf("\n");
		break;
	}
		
	while(1)
	{
		printf("输入要访问的页面序列个数(P<=100):\n");
		scanf("%d",&page_num);			
		if(page_num>100)
			printf("请重新输入");
		printf("\n");
		break;
	}
	
	printf("请依次输入要访问的页面序列:\n");
	for(i=0;i<page_num;i++)
	{
		scanf("%d",&page[i]);
		Que[i] = 'N';
	}
		 	
	for(i=0;i<block_num;i++)
	     memory[i]=-1;   //初始内存块中默认为空,用-1表示
 
    //访问页面
	for(i=0;i<page_num;i++)
	{
		if(i==0)   //访问的第一个页面
		{
			memory[i]=page[i];
			reg[i]=i;
			for(j=0;j<block_num;j++)
				table[i][j]=memory[j];
			Que[i]='Y';
			count++;
		}
		else
		{    /*判断新页面号是否在物理块中*/   
			for(j=0,k=0;j<block_num;j++)
			{
				if(memory[j]!=page[i])
					k++;
				else
				{    /*新页面在内存块中*/
					reg[j]=i;  //刷新该页面的访问时间
					for(int n=0;n<block_num;n++)
						table[i][n]=memory[n];
				}
			}
		}
		if(k==block_num)   /*新页面不在物理块中,缺页*/
		{
			int q=0;
			Que[i]='Y';
		    count++;
			for(int j=0;j<block_num;j++)
			{
				if(memory[j]==-1)   /*内存块未满*/
				{
					memory[j]=page[i];
				    reg[j]=i;
				    for(int n=0;n<block_num;n++)
					    table[i][n]=memory[n]; 
					break;
				}
				else   
					q++;	
			}
			if(q==block_num)/*内存块已满,需采用LRU置换算法选择换出页*/ 
			{
			    int min=0;  //记录换出页
        	    for(int m=1;m<block_num;m++)
			        if(reg[m]<reg[min])
				    	min=m;
		        memory[min]=page[i];
                reg[min]=i; /*记录该页的访问时间(新到的页面进入之前min的位置,需将min位置的访问时间更改)*/
                for(int n=0;n<block_num;n++)
			       table[i][n]=memory[n];
			}
		}
    }
    
 	/*输出运行过程及结果*/   
	printf("采用LRU页面置换算法结果如下: \n");
	printf("\n");
	printf("\n");
	printf("页号:");
	for(i=0;i<page_num;i++)
		printf("%3d",page[i]);
	printf("\n");
	printf("-----------------------------------------------------\n");
	for(i=0;i<block_num;i++) 	
	{
		printf("块%2d:",i);	 
		for(j=0;j<page_num;j++)
			printf("%3d",table[j][i]);
		printf("\n");
	}
    printf("-----------------------------------------------------\n");
	printf("缺页:");
	for(i=0;i<page_num;i++)
	    printf("%3c",Que[i]);
	printf("\n");
	
	printf("-----------------------------------------------------\n");
	printf("\t缺页次数:%d\n",count);
	printf("\t缺页率:%d/%d\n",count,page_num);
	printf("-----------------------------------------------------\n");
}

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

佳美不ERROR

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

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

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

打赏作者

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

抵扣说明:

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

余额充值