作業系統實驗五
阿新 • • 發佈:2021-12-12
頁面置換演算法
題目
設程序的邏輯地址空間共分為8個頁面,程序執行時需引用的頁面號引用串為7、0、1、2、0、3、0、4、2、3、0、3、2、1、2、0、1、7、0、1,現系統為該程序在記憶體中分配了三個物理儲存塊。請根據理論教材所授內容,採用C語言(也可採用自己熟悉的語言)分別模擬實現OPT、FIFO、LRU、NRU和LFU頁面置換演算法,對上述頁面號引用串進行排程,並計算出各演算法下的缺頁率。
程式碼如下:
OPT頁面置換演算法 #include <iostream> #include<map> #include<set> #include <algorithm> #include<cstdio> #include<cstring> #include<cmath> #define N 200 using namespace std; int page[N];//頁面引用號 int block[N];//物理塊,記憶體 int dist[N][N];//表示第i次訪問記憶體的時候,記憶體中的頁面j 在以後被訪問的最小時間 int n;//頁面引用號個數 int m;//物理塊數目 int page_max;//最大頁面號 int pre[N];//page[i]在page中的索引 int opt(){//最佳頁面置換演算法 int page_lack = 0; memset(pre, 0, sizeof(pre)); memset(dist, 0x3f, sizeof(dist)); memset(block, -1, sizeof(block)); for(int i=n; i>=1; --i){ for(int j=0; j<=page_max; ++j) if(pre[j]) dist[i][j] = pre[j] - i; pre[page[i]] = i; } for(int i=1; i<=n; ++i){//開始訪問頁面 int j; int max_dist = 0, p; for(j=1; j<=m; ++j){ if(block[j] == -1){//該物理塊中沒有被放入頁面,則直接放入, 產生缺頁 block[j] = page[i]; cout<<"頁面"<<page[i]<<"不在記憶體,直接放入物理塊"<<j<<"中!"<<endl; page_lack++; break; } else if(block[j] == page[i])//頁面存在記憶體中 break; if(max_dist < dist[i][block[j]]){ max_dist = dist[i][block[j]];//說明block[j] 對應的頁面以後會長時間不會用到 p = j;//block[] 第j個頁面會被替換掉 } } if(j > m){//此時物理塊中被裝滿,且沒有找到page[i]對應的分頁,接下來進行頁面替換 cout<<"頁面"<<page[i]<<"不在記憶體,將物理塊"<<p<<"中的頁面" <<block[p]<<"替換掉!"<<endl; block[p] = page[i]; page_lack++; } cout<<endl<<"當前記憶體中頁面的情況:"<<endl; for(int k=1; k<=m; ++k)//記憶體中頁面載入情況 cout<<block[k]<<" "; cout<<endl<<endl; } return page_lack;//返回缺頁次數 } int main(){ int page_lack; float w;//w為缺頁中斷率 cout<<"請輸入頁面引用號個數" ; cin>>n; cout<<"請輸入物理塊個數"; cin>>m; cout<<"輸入頁面引用序列"; for(int i=1; i<=n; ++i){ cin>>page[i]; page_max = max(page_max, page[i]) ; } page_lack=opt(); w=(float)page_lack/n; cout<<"OPT缺頁中斷次數:"<<page_lack<<endl; cout<<"缺頁中斷率:"<<w<<endl; return 0; }
執行截圖:
FIFO頁面置換演算法
#include <iostream> #include<map> #include<set> #include <algorithm> #include<cstdio> #include<cstring> #include<cmath> #define N 200 using namespace std; int page[N];//頁面引用號 int block[N];//物理塊,記憶體 int dist[N][N];//表示第i次訪問記憶體的時候,記憶體中的頁面j 在以後被訪問的最小時間 int n;//頁面引用號個數 int m;//物理塊數目 int page_max;//最大頁面號 set<int>page_set; int fifo(){//先進先出頁面置換演算法 int page_lack = 0; memset(block, -1, sizeof(block)); int index = 1; for(int i=1; i<=n; ++i){ if(index > m) index = 1; set<int>::iterator it; it = page_set.find(page[i]); if(it == page_set.end()){ if(block[index] != -1) page_set.erase(block[index]); page_set.insert(page[i]); block[index++] = page[i]; ++page_lack; } for(int k=1; k<=m; ++k) cout<<block[k]<<" "; cout<<endl; } return page_lack; } int main(){ int v;//w為缺頁率 ,v為缺頁中斷次數 float w; cout<<"請輸入頁面引用號個數" ; cin>>n; cout<<"請輸入物理塊個數"; cin>>m; cout<<"請輸入頁面號引用次序"; for(int i=1; i<=n; ++i){ cin>>page[i]; page_max = max(page_max, page[i]) ; } v=fifo(); w=(float)v/n; cout<<"FIFO缺頁中斷次數:"<<v<<endl; cout<<"FIFO缺頁中斷率:"<<w<<endl; return 0; }
執行截圖:
LRU演算法
#include <iostream> #include<map> #include<set> #include <algorithm> #include<cstdio> #include<cstring> #include<cmath> #define N 200 using namespace std; int page[N];//頁面引用號 int block[N];//物理塊,記憶體 int dist[N][N];//表示第i次訪問記憶體的時候,記憶體中的頁面j 在以後被訪問的最小時間 int n;//頁面引用號個數 int m;//物理塊數目 int page_max;//最大頁面號 int pre[N];//page[i]在page中的索引 int LRU(){ int page_lack = 0;//page_back為缺頁次數 memset(pre, 0, sizeof(pre)); memset(dist, 0x3f, sizeof(dist)); memset(block, -1, sizeof(block)); for(int i=1; i<=n; ++i){ for(int j=0; j<=page_max; ++j) if(pre[j]) dist[i][j] = i - pre[j]; pre[page[i]] = i; } for(int i=1; i<=n; ++i){//開始訪問頁面 int j; int max_dist = 0, p; for(j=1; j<=m; ++j){ if(block[j] == -1){//該塊沒有放入頁面,則直接放入, 產生缺頁 block[j] = page[i]; cout<<"頁面"<<page[i]<<"不在記憶體,直接放入物理塊"<<j<<"中!"<<endl; page_lack++; break; } else if(block[j] == page[i])//頁面存在記憶體中 break; if(max_dist < dist[i][block[j]]){ max_dist = dist[i][block[j]]; p = j;//block[] 第j個頁面會被替換掉 } } if(j > m){ cout<<"頁面"<<page[i]<<"不在記憶體,將物理塊"<<p<<"中的頁面" <<block[p]<<"替換!"<<endl; block[p] = page[i]; page_lack++; } cout<<endl<<"當前記憶體中頁面的情況:"<<endl; for(int k=1; k<=m; ++k)//記憶體中頁面載入情況 cout<<block[k]<<" "; cout<<endl<<endl; } return page_lack; } int main(){ cout<<"請輸入頁面引用號個數" ; cin>>n; cout<<"請輸入物理塊個數"; cin>>m; cout<<"請輸入頁面引用次序"; for(int i=1; i<=n; ++i){ cin>>page[i]; page_max = max(page_max, page[i]) ; } int lack=LRU(); float w; w=(float)lack/n; cout<<"LRU缺頁中斷次數:"<<lack<<endl; cout<<"缺頁中斷率"<<w<<endl; return 0; }
執行結果截圖:
後續兩個演算法實驗並未完成,因此給出老師所給的程式碼作為參考
NRU演算法
void NRU (int ref_len, int vsize){
int i, find, miss, rep, least;
int flag[MEM_FRAME_SIZE]; //訪問位
float rate = 0;
printf("-------(4) NRU頁面缺頁演算法-------\n");
miss = 0;
ini_mem (); //初始化記憶體迴圈頁框
for (i = 0; i < MEM_FRAME_SIZE; i ++) //初始化記憶體迴圈頁框的訪問位
flag[i] = 0;
rep = 0;
for (i = 0; i < ref_len; i ++) {
find = search (MEM_FRAME_SIZE, reference[i]);
if (find != FALSE && mem_frame[find] == -1) { //記憶體迴圈頁框未滿
miss ++;
mem_frame[find] = reference[i];//頁面缺頁
printf("頁框未滿,置入頁面%d\n",reference[i]);
flag[rep] = 1; // 置訪問為1
rep = (rep+1) % MEM_FRAME_SIZE; //頁面不在記憶體中,掃描指標下移
}
else if (find == FALSE) { //記憶體迴圈頁框已滿且擬置入頁面不在頁框中
miss ++;
while (flag[rep] != 0) { //最近被使用過,給第二次機會
flag[rep] = 0;
rep = (rep+1) % MEM_FRAME_SIZE;
}
printf("換出頁面%d,換入頁面%d\n",mem_frame[rep],reference[i]);
mem_frame[rep] = reference[i];//頁面缺頁
flag[rep] = 1; // 置訪問為1
rep = (rep+1) % MEM_FRAME_SIZE; //頁面不在記憶體中,掃描指標下移
}
else{//在記憶體迴圈頁框中找到擬置入頁面
printf("記憶體頁框中存在頁面%d,無需置入\n",reference[i]);
flag[find] = 1; //頁面的記憶體中,掃描指標不動
}
}
rate = (float)miss/(float)ref_len; //計算頁面缺頁率
printf("-----NRU頁面缺頁率為:%d/%d=%.2f-----\n\n",miss,ref_len,rate);
}
LFU演算法
void LFU (int ref_len, int vsize){
int i, j, find, miss, rep, least;
int count[MEM_FRAME_SIZE]; //計數器:記錄記憶體頁框中頁面的使用頻率
float rate = 0;
printf("-------(5) LFU頁面缺頁演算法-------\n");
miss = 0;
ini_mem (); //初始化記憶體頁框
for (i = 0; i < MEM_FRAME_SIZE; i ++) //初始化記憶體頁框中頁面的使用頻率
count[i] = 0;
for (i = 0; i < ref_len; i ++) {
find = search (MEM_FRAME_SIZE, reference[i]);
if (find != FALSE && mem_frame[find] == -1) { //記憶體頁框未滿
miss ++;
mem_frame[find] = reference[i];//頁面缺頁
printf("頁框未滿,置入頁面%d\n",reference[i]);
}
else if (find == FALSE) { //記憶體頁框已滿且擬置入頁面不在頁框中
miss ++;
least = count[0];
rep = 0;
for (j = 1; j < MEM_FRAME_SIZE; j ++) {//選擇記憶體頁框中使用頻率最小的頁面
if (count[j] < least) {
least = count[j];
rep = j;
}
}
printf("換出頁面%d,換入頁面%d\n",mem_frame[rep],reference[i]);
mem_frame[rep] = reference[i];//頁面缺頁
count[rep] = 0;
}
else{//在記憶體頁框中找到擬置入頁面
printf("記憶體頁框中存在頁面%d,無需置入\n",reference[i]);
count[find] ++;
}
if ((i+1) % 4== 0) { //沒有移位暫存器,用計數器定期衰減模擬移位,如果把4改成10,缺頁率結果又如何?
for (j = 0; j < MEM_FRAME_SIZE; j ++)
count[j] /= 2; //移位
}
}
rate = (float)miss/(float)ref_len; //計算頁面缺頁率
printf("-----LFU頁面缺頁率為:%d/%d=%.2f-----\n\n",miss,ref_len,rate);
}
OPT、FIFO、LRU、NRU和LFU頁面置換演算法優缺點分析
本次實驗有一定的難度,尤其是後面兩個演算法的思想和如何實現,後續有時間還要再研究