1. 程式人生 > >頁面置換演算法——最近最久未使用演算法(c語言實現)

頁面置換演算法——最近最久未使用演算法(c語言實現)

作業系統實驗:用C語言程式設計實現最近最久未使用置換演算法(LRU)

最近最久未使用置換演算法(LRU),全稱Least Recently Used,是一種頁面置換演算法。

對於在記憶體中但又不用的資料塊(記憶體塊)叫做LRU,作業系統會根據哪些資料屬於LRU而將其移出記憶體而騰出空間來載入另外的資料。

簡單概括其思想:

1.根據頁面調入記憶體後的使用情況。
2.利用“最近的過去”作為“最近的將來”的近似。
3.選擇最近最久未使用的頁面予以淘汰。

 一般有3種方法

1.陣列+時間戳

2.棧

3.佇列

 其中棧和佇列可以選擇順序型或者是鏈型。

手工棧和佇列程式碼冗長,順序棧和順序佇列不方便從中間改動資料。鏈型初始化較麻煩,且考慮細節較多。主要介紹陣列+時間戳法。

演算法思路:

用一個數組來儲存資料,給每一個數據項標記一個訪問時間戳,每次插入新資料項的時候,先把陣列中存在的資料項的時間戳自增,並將新資料項的時間戳置為0並插入到陣列中。每次訪問陣列中的資料項的時候,將被訪問的資料項的時間戳置為0。當陣列空間已滿時,將時間戳最大的資料項淘汰。

所以要用此方法,必須定義一個二維陣列或者是結構體,我結合了時間戳、棧和順序表的思路,重新設計了一個較好的方法。

程式碼如下:

#include<stdio.h>
#define MAX 100

int judge(int a[],int n,int x)		//判斷陣列中是否已有x,若有返回其下標值,沒有則返回-1 
{
	int i;
	for(i=0;i<n;i++)
		if(x==a[i])
			return i;
	return -1;
}

void init(int a[],int n)		//初始化陣列為-1 
{
	int i;
	for(i=0;i<n;i++)
		a[i]=-1;
}

void insert(int a[],int n,int x)	//棧法插入(第一個元素出,後面元素前移,新元素從尾部入) 
{
	int i;
	for(i=0;i<n-1;i++)
		a[i]=a[i+1];
	a[n-1]=x;
}

void move(int a[],int n,int i)		//移動下標為i的元素到尾部 
{
	int j;
	int m=a[i];
	for(j=i;j<n-1;j++)
		a[j]=a[j+1];
	a[n-1]=m;
} 

void print(int a[],int n)		//輸出當前陣列元素 
{
	int i;
	for(i=0;i<n;i++)
		if(a[i]!=-1)
			printf(" %d",a[i]);
	printf("\n");
}

int main()
{
	int stack[MAX];
	int top=-1;			//模仿棧的定義 
	int n,x;
	printf("請輸入物理塊數:\n");
	scanf("%d",&n);		 
	init(stack,n);			//初始化陣列 
	printf("請輸入記憶體訪問序列:\n");
	while(~scanf("%d",&x))		//自動讀數 
	{
		printf("訪問頁面%d:\n",x);
		top++;			//讀數後top自動+1 
		if(top==0)		//若陣列無元素
			stack[top]=x;	//插入一個元素 
		else if(top<n)		//若在物理塊範圍內 
		{
			if(judge(stack,n,x)==-1)//若陣列中不存在待插入元素 
				stack[top]=x;	//新元素從尾部插入 
			else			//若陣列中存在待插入元素
			{
				move(stack,top,judge(stack,n,x));//移動下標為i的元素到尾部 
				top--;				//因為沒有插入新元素,回滾top值 
			}
		}		
		else				//超過物理塊數的元素 
		{
			if(judge(stack,n,x)==-1)//若陣列中不存在待插入元素
			{
				insert(stack,n,x);	 //棧法插入(第一個元素出,後面元素前移,新元素從尾部入)
				top--;			//因為沒有插入新元素,回滾top值
			}
			else				//若陣列中存在待插入元素
			{
				move(stack,n,judge(stack,n,x));//移動下標為i的元素到尾部
				top--;			//因為沒有插入新元素,回滾top值 
			}
		}
		print(stack,n);				//讀一個序列號,輸出當前陣列元素 
	}
	
	return 0;
}

  

執行結果:

作業系統確實博大精深,想想當初開發作業系統的計算機先驅們真是偉大,一點點從硬體層開發到軟體層,這期間遇到了多少問題,耗費了多少精力,再次膜拜他們~

果然只有自己動手把程式碼敲出來才算真正理解了一個演算法,學程式設計一定要動手,不怕難,多思考,才能進步啊~