頁面置換算法
百度百科對頁面置換算法給出的定義:在地址映射過程中,若在頁面中發現所要訪問的頁面不在內存中,則產生缺頁中斷。當發生缺頁中斷時,如果操作系統內存中沒有空閒頁面,則操作系統必須在內存選擇一個頁面將其移出內存,以便爲即將調入的頁面讓出空間。而用來選擇淘汰哪一頁的規則叫做頁面置換算法。
問題:隨機一訪問串和駐留集的大小,通過模擬程序顯示淘汰的頁號並統計命中率。示例:
輸入訪問串:7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1
駐留集大小:3
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1
7 7 7 2 2 2 2 4 4 4 0 0 0 0 0 0 0
0 0 0 0 3 3 3 2 2 2 2 2 1 1 1 1
1 1 1 1 0 0 0 3 3 3 3 3 2 2 2
7 0 1 2 3 0 4 2 3
紅色表示:指針指向調入內存的頁面中“最老“的頁面
通過模擬程序輸出淘汰的頁號分別爲:7 0 1 2 3 0 4 2 3
命中率爲:5/13
注意:內存的頁面中“最老“的頁面,會被新的網頁直接覆蓋,而不是“最老“的頁面先出隊,然後新的網頁從隊尾入隊。
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int len;
typedef struct Queue
{
int * pBase;
int front;//隊列頭
int rear;//隊列尾
}QUEUE;
void init(QUEUE *pQ)
{
int N = len+1;
pQ->pBase = (int *)malloc(sizeof(int ) * N);//N爲數組長度
//初始化爲0
pQ->front = 0;
pQ->rear = 0;
}
int full_queue(QUEUE *pQ)
{
int N = len+1;
if((pQ->rear +1)%N == pQ->front)//循環隊列
return 1;
else
return 0;
}
int en_queue(QUEUE *pQ, int val)//入隊前判斷隊列是否已滿
{
int N = len+1;
if( full_queue(pQ) )
{
return 0;
}
else
{
pQ->pBase[pQ->rear] = val;//壓棧在隊尾
pQ->rear = (pQ->rear+1) % N;
return 1;
}
}
int empty_queue(QUEUE *pQ)
{
int N = len+1;
if(pQ->front == pQ->rear)
return 1;
else
return 0;
}
int out_queue(QUEUE *pQ, int *pVal)//出隊前判斷隊列是否爲空
{
int N = len+1;
if(empty_queue(pQ))
{
return 0;
}
else
{
*pVal = pQ->pBase[pQ->front];//把出隊的元素保存起來
pQ->front = (pQ->front+1)%N;
return 1;
}
}
int same_queue(QUEUE *pQ, int x)
{
int N = len+1;
int i = pQ->front;
while( i != pQ->rear)
{
if( pQ->pBase[i] == x)
return 1;
i = (i+1) % N;
}
return 0;
}
int main()
{
int cnt = 0;//記沒命中次數
int i, val, data;
char str[1000];
scanf("%d", &len);//駐留集大小
scanf("%s", str);
QUEUE Q;
init (&Q);
for(i=0; str[i] != '\0'; i++)
{
if(str[i] >= '0' && str[i] <= '9')
{
val= str[i] - '0';
if( !full_queue(&Q) && !(same_queue(&Q, val)))
{
en_queue(&Q, val);
cnt++;
}
else if( full_queue(&Q) && !(same_queue(&Q, val)) )
{
out_queue(&Q, &data);
printf("%d ",data);
en_queue(&Q, val);
cnt++;
}
}
}
printf("\n%d/%d", strlen(str)- cnt, strlen(str));
return 0;
}
(3)LRU頁面置換算法(最近未使用頁面置換算法)問題:隨機一訪問串和駐留集的大小,通過模擬程序顯示淘汰的頁號並統計命中率。示例:
輸入訪問串:7 0 1 2 0 3 0 4 2 3 0 3 2
駐留集大小:3
算法的實現:由於LRU算法淘汰的是上次使用距離t時刻最遠的頁,故需記錄這個距離。
計數器:可使用計數器,給每一個頁幀增設一個計數器。每訪問一頁,就把對應頁幀的計數器清零,其餘頁幀的計數器加1.因此,計數器值爲最大的頁即上次訪問距當前最遠的頁。
7 0 1 2 0 3 0 4 2 3 0 3 2
0/7 1/7 2/7 0/2 1/2 2/2 3/2 0/4 1/4 2/4 0/0 1/0 2/0
0/0 1/0 2/0 0/0 1/0 0/0 1/0 2/0 0/3 1/3 0/3 1/3
0/1 1/1 2/1 0/3 1/3 2/3 0/2 1/2 2/2 3/2 0/2
缺 缺 缺 缺 命 缺 命 缺 缺 缺 缺 命 命
紅色表示:每個頁幀對應的計數器值
通過模擬程序輸出淘汰的頁號分別爲:7 1 2 3 0 4
命中率爲:4/13
LRU的另一種通俗理解:
例如一個三道程序,等待進入的是1,2,3,4,4,2,5,6,3,4,2,1。先分別把1,2,3導入,然後導入4,置換的是1,因爲他離導入時間最遠。然後又是4,不需要置換,然後是2,也不需要,因爲內存中有,到5的時候,因爲3最遠,所以置換3,依次類推
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int len;
typedef struct LRU
{
int data;
int time;//計次數
} LRU;
typedef struct Queue
{
LRU *pBase;//結構數組
int front;//隊列頭
int rear;//隊列尾
}QUEUE;
void init(QUEUE *pQ)
{
int N = len+1;
pQ->pBase = (LRU*)malloc(sizeof(LRU ) * N);
pQ->front = pQ->rear = 0; //初始化爲0
}
int full_queue(QUEUE *pQ)
{
int N = len+1;
if((pQ->rear +1)%N == pQ->front)//循環隊列
return 1;
else
return 0;
}
int en_queue(QUEUE *pQ, int val)//入隊前判斷隊列是否已滿
{
int N = len+1;
if( full_queue(pQ) )
{
return 0;
}
else
{
pQ->pBase[pQ->rear].data = val;//壓棧在隊尾
pQ->pBase[pQ->rear].time = 0;//初始化次數爲0
pQ->rear = (pQ->rear+1) % N;
return 1;
}
}
int empty_queue(QUEUE *pQ)//1-->空 0-->非空
{
int N = len+1;
if(pQ->front == pQ->rear)
return 1;
else
return 0;
}
int out_queue(QUEUE *pQ, int *pVal)//出隊前判斷隊列是否爲空
{
int N = len+1;
if(empty_queue(pQ))
{
return 0;
}
else
{
*pVal = pQ->pBase[pQ->front].data;//把出隊的元素保存起來
pQ->front = (pQ->front+1)%N;
return 1;
}
}
void add_time(QUEUE *pQ)
{
int N = len+1;
int i = pQ->front;
while( i != pQ->rear)
{
pQ->pBase[i].time ++;
i = (i + 1) % N;
//printf("%d %d", pQ->pBase[i].time, i);
}
}
void Set_time_shot(QUEUE *pQ, int x)//若待入隊元素與隊中元素相同,將次數置爲0
{
int N = len + 1;
int i = pQ->front;
while( i != pQ->rear)
{
if( pQ->pBase[i].data == x)
{
pQ->pBase[i].time = 0;
}
i = (i+1) % N;
}
}
int Find_big_time(QUEUE *pQ)
{
int N = len + 1;
int i = pQ->front;
int max_i = i;
int max_time = pQ->pBase[pQ->front].time;
while( i != pQ->rear)
{
if( pQ->pBase[i].time > max_time)
{
max_i = i; max_time = pQ->pBase[i].time;
}
i = (i+1) % N;
}
return max_i;
}
void Replace_big_time(QUEUE *pQ, int x)//若待入隊元素與隊中元素不相同,替換元素,並將次數置爲0
{
int max_time = Find_big_time(pQ);
printf("%d ", pQ->pBase[max_time].data);
pQ->pBase[max_time].data = x;
pQ->pBase[max_time].time = 0;
}
int same_queue(QUEUE *pQ, int x)//判斷待入隊元素是否與隊中元素相同
{
int N = len+1;
int i = pQ->front;
while( i != pQ->rear)
{
if( pQ->pBase[i].data == x)
return 1;
i = (i+1) % N;
}
return 0;
}
int main(void)
{
char str[100];
int val, data;
int i, cnt = 0;
scanf("%d", &len);
scanf("%s", str);
QUEUE Q;
init(&Q);
for(i=0; str[i] != '\0'; i++)
{
val = str[i] - '0';
if ( empty_queue( &Q ) )//如果隊列爲空
{
en_queue(&Q, val);
}
else
{
add_time(&Q);
if(full_queue(&Q))//如果隊列已滿
{
if( !same_queue(&Q, val))
{
Replace_big_time(&Q, val);
}
else
{
Set_time_shot(&Q, val);
cnt++;
}
}
else//如果隊列沒滿也不爲空
{
if( !same_queue(&Q, val))
{
en_queue(&Q, val);
}
else
{
Set_time_shot(&Q, val);
cnt++;
}
}
}
}
printf("\n%d/%d", cnt, strlen(str));
return 0;
}
注意:雖然兩個算法都是用隊列這種數據結構實現的,但具體操作不完全遵從隊列的原則。這一點不必糾結。
哈爾濱工業大學2000年考研操作系統真題操作系統考研輔導教程87頁一請求分頁存儲系統,進程P共有5頁,訪問串爲3,2,1,0,3,2,4,3,2,1,0,4,試採用LRU算法和LFU算法分析,當分配頁面數爲3時,發生的缺頁中斷次數。解:
least frequently used (LFU),要求在頁置換時置換引用計數最小的頁。 3,2,1 0進入時,缺頁。置換最近最小的1。內存:3,2,0 3,2 4進入時,缺頁。置換最近最小的0。內存:3,2,4 3,2 1進入時,缺頁。置換最近最小的4。內存:3,2,1 0進入時,缺頁。置換最近最小的1。內存:3,2,0 4進入時,缺頁。置換最近最小的0。內存:3,2,4