課程設計課題
存儲管理程序設計
摘 要
虛擬存儲器作為現代操作系統中存儲管理的一項重要技術,實現了內存擴充功能。而分頁請求分頁系統正好可以完美的支持虛擬存儲器功能,它具有請求調頁功能和頁面置換功能。在進程運行過程中。若其所訪問的頁面不存在,而需把他們調入內存,但內存無空閑時間時,為了保證該程序能夠正常運行,系統必須從內存中調出一頁程序或數據送到磁盤的兌換區中,通常,把選擇換出頁面的算法稱為頁面置換算法。一個好的置換算法應該具有較低的頁面更換頻率,所以本次實驗中用了FIFO,LRU,OPT三種重要的置換算法。
關鍵詞:分頁;虛擬存儲;FIFO;LRU;OPT;
一、課程設計的目的和要求
1、目的:存儲管理的主要功能之一是合理地分配空間。請求頁式管理是一種常用的虛擬存儲管理技術。本次設計的目的是通過請求頁式存儲管理中頁面置換算法模擬設計,了解虛擬存儲技術的特點,掌握請求頁式管理的頁面置換算法。
2、要求:
(1).過隨機數產生一個指令序列,共320條指令。其地址按下述原則生成:
①50%的指令是順序執行的;
②25%的指令是均勻分布在前地址部分;
③25%的指令是均勻分布在后地址部分;
(2). 指令序列變換成頁地址流
(3). 計算並輸出下述各種算法在不同內存容量下的命中率。
二、系統需求分析與總體設計
存儲管理程序是可以進行合理的分配空間,而請求頁式管理是一種常用的虛擬存儲管理技術,通過這種技術用三種不同的算法來分配地址空間,算出這三種算法的命中率。
1、定義頁面的結構(既然用到了分頁式管理就要先定義頁面)
2、函數定義
3、寫主函數用來調用三種算法
4、寫好三種算法分別為:
(1) FIFO(先進先出算法)這個算法的基本思想是:總是先淘汰一些駐留在內存時間最長的頁面,即先進入內存的頁面先被置換掉
(2) LRU(最近最少使用算法)本算法的基本思想是:如果某一頁被訪問了,那么它很可能馬上又被訪問;反之,如果某一頁很長時間沒有被訪問,那么最近也不太可能會被訪問。
(3) OPT(最優算法)這是最理想的頁面置換算法:從內存中移出以后不再使用的頁面;如無這樣的頁面,則選擇以后最長時間內不需要訪問的頁面。
5、程序總體設計框圖
|
Main( ) |
|
Initialize(pf) 框架初始化函數 |
|
FIFO 算法 |
|
LRU 算法 |
|
OPT 算法 |
三、詳細設計
本實驗中,命中率=1-頁面失效次數/頁地址流長度;在本實驗中,頁地址流長度為320,頁面失效次數為每次訪問相應指令時,該指令所對應的頁不在內存的次數;隨機數產生辦法,由系統提供函數strand()和rand(),分別進行初始化和產生隨機數。
1、定義頁面的結構
Typedef struct
{
Int pn,pfn,count,time;
}
pl_type; 其中pn為頁號,pfn為面號,count為個周期內訪問該頁面次數time為訪問時間。
2、函數定義
(1)void initialize():初始化函數,給每個相關的頁面賦值。
(2)void FIFO():計算使用FIFO算法時的命中率。
(3)void LRU():計算使用LRU算法時的命中率。
(4)void OPT():計算使用OPT算法時的命中率。
3、主函數Main()
|
開始 |
(1).先找出是否有指令,產生指令隊列(2).再按照要求的方法執行指令(3).將指定指令列轉換成頁地址流(題目中要求的是每頁十個指令)(4).依次執行三種算法得出命中率
4、三種算法
(1)FIFO這個算法的基本思想是:總是
先淘汰一些駐留在內存時間最長的頁面,
|
是否有指令 |
即先進入內存的頁面先被置換掉。作業
只要把進入內存的各個頁面按進入的時
|
計算出頁號 |
間次序用鏈表鏈接起來,設定一個鏈表
首指針指向進入內存最早的一個頁面,
新進入的頁面放在鏈表的尾部,需要淘
汰某一個頁面時,總是淘汰替換指針所
|
在實存隊列查找該頁號 |
指向的頁面即可。先進先出算法在程序
按線性順序訪問邏輯地址空間時比較理
|
是否找到 |
想,否則效率不高。特別是在遇到循環
執行的程序段時,往往會把頻繁訪問的
頁面,因其在內存駐留時間過長, yes
而周期性地淘汰掉。
no
|
新頁號按序列加入實存序列 |
FIFO算法
|
計算出命中率 |
|
結束 |
|
開始 |
(2)LRU算法: 他的的基本思想是:如果某一頁
被訪問了,那么它很可能馬上又被訪問;反之,
如果某一頁很長時間沒有被訪問,那么最近也不
|
是否有指令 |
太可能會被訪問。這種算法考慮了程序設計的局
|
把新頁放入隊列,同時向下移動其余頁號 |
部性原理。其實質是:當需要置換一頁時,選擇
最近一段時間內最久未使用的頁面予以淘汰。
|
計算出頁號 |
|
在實存隊列中查找該頁號 |
|
是否找到 |
|
新頁進入隊列,老頁號移出 |
N
|
計算出命中率 |
|
結束 |
(3)OPT算法:這是最理想的頁面置換算法:從內存中移出以后不再使用的頁面;如無這樣的頁面,則選擇以后最長時間內不需要訪問的頁面。本算法因為頁面訪問的順序是很難預知的,所以不是一種實際的方法。
|
開始 |
|
是否有指令 |
|
計算出頁號 |
Yes
|
在頁面中查找是否存在 |
|
是否找到 |
|
將該頁面導入空閑頁面 |
no
|
是否有空閑頁面 |
yes
no
|
計算出命中率 |
|
結束 |
|
按照指令隊列查找以后指令找出每一頁命中的距離,找出最大的或沒命中的當前空閑頁面 |
四、測試、調試過程
1、實驗過程中遇到的問題:
起初開始接觸題目的時候除了知道三種算法是怎么進行之外對於存儲是一無所知,尤其是頁式虛擬存儲,后來經過網上查找資料才知道請求頁式管理的調入方式是,當需要執行某指令二又發現它不在內存時或當執行某條指令需要訪問其他數據或指令時,這些指令和數據不在內存中,從而發生缺頁中斷,系統將外出中相應的頁面調入內存。
還有開始的時候需要生成隨機數,后來進過查找才知道原來隨機數還可以通過系統提供函數進行初始化和產生隨機數
2、實驗截圖
五、結論與體會
通過切實的實驗與分析,鞏固了所學的有關頁式存儲管理的相關知識,更深層次地理解並掌握了LRU和隨機淘汰算法的精髓。通過使用C語言模擬LRU和隨機算法實現請求頁式管理,進一步提高了我的編程能力,並且有助於將操作系統和C有機地結合起來,使我更加明白了學科之間是緊密聯系的。此外,經過這次課程設計,我更加感悟到了,僅僅學習書本上的理論知識是不夠的,要在平時多進行實際操作,這樣才能融會貫通,更加牢固地掌握所學知識。在以后的學習過程中,我應該更加深入學習有關C的內容,提高自己的動手能力。我對於存儲系統的了解大大的加深了,所有的東西都再是紙上談兵,從基礎的三種算法的實現:先進先出(FIFO)、最近最少使用(LRU)、最佳淘汰(OPT)、,可以清晰看出操作系統中一些原理性的東西,他的運行,他的工作方式,不只是靠自己對着課本的文字去想想了。
而通過最優、最先、最差三種適應算法來對主存實現分配的過程中,更是深刻的體會到其中的微妙。分頁管理中的運行結果出現之后一目了然,隊列方式也是方便自如。是讓書上不動的文字活了起來。
整個實驗下來,無論是翻課本查原理,還是上百度搜代碼,都是促進我們學習實踐的一大助力,讓課堂上一些死板的知識流轉在手指之間,躍現在熒屏上面。
六、參考文獻
【1】 計算機操作系統 西安電子科技大學出版社。湯子瀛、哲鳳屏、湯小丹編著
【2】VC++深入詳解 電子工業出版社 。孫鑫 余安萍編著
【3】張堯學,史美林編著.計算機操作系統教程(第三版).清華大學出版社.2006
【4】http://www.baidu.com
。。。。。。
附錄:源程序
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define TRUE 1
#define FALSE 0
#define INVALID -1
#define NULL 0
#define zllc 320
#define xy 32
#define clear 100
/*以下統一解釋 pn:page number,pfn:page frame number,pfc:page frame control*/
typedef struct /*頁面結構*/
{
int pn; //頁號
int pfn; //頁面框架號
int count; //計數器
int time; //時間
}
pc;
pc pl[xy]; /*頁面線性結構---指令序列需要使用地址*/
typedef struct pfc_struct /*頁面結構控制,調度算法的控制結構*/
{
int pn;
int pfn;
struct pfc_struct *next;
}
pfc_type;
pfc_type pfc[xy], *free_head, *busy_head, *busy_tail;
int zhihuan, a[zllc]; /* a[]為指令序列*/
int page[zllc], offset[zllc]; /*地址信息*/
int initialize(int);
int FIFO(int);
int LRU(int);
int OPT(int);
/*初始化pf*/
int initialize(int pf)
{
int i;
zhihuan=0;
for(i=0;i<xy;i++)
{
pl[i].pfn=INVALID; /*置頁面控制結構中的頁號,頁面為空*/
pl[i].count=0; /*頁面控制結構中的訪問次數為0*/
pl[i].time=-1; /*訪問的時間*/
}
for(i=0;i<pf-1;i++) /*建立pfc[i-1]和pfc[i]之間的鏈接*/
{
pfc[i].next=&pfc[i+1];
pfc[i].pfn=i;
}
pfc[pf-1].next=NULL;
pfc[pf-1].pfn=pf-1;
free_head=&pfc[0]; /*空頁面隊列的頭指針為pfc[0]*/
return 0;
}
/*先進先出算法*/
int FIFO(int pf)
{
int i;
pfc_type *p; /*中間變量*/
initialize(pf); /*初始化相關頁面控制用數據結構*/
busy_head=busy_tail=NULL; /*忙頁面隊列頭,隊列尾鏈接*/
for(i=0;i<zllc;i++)
{
if(pl[page[i]].pfn==INVALID) /*頁面失效*/
{
zhihuan++; /*失效次數*/
if(free_head==NULL) /*無空閑頁面*/
{
p=busy_head->next; //保存忙頁面下一個頁面
pl[busy_head->pn].pfn=INVALID; //把這個頁面換出,更新它的數據成員
free_head=busy_head; /*釋放忙頁面隊列的第一個頁面*/
free_head->next=NULL; /*表明還是缺頁*/
busy_head=p; //更新忙頁面的隊頭指針
}
p=free_head->next;
free_head->pn=page[i];
pl[page[i]].pfn=free_head->pfn;
free_head->next=NULL;
/*使busy的尾為null*/
if(busy_tail==NULL)
{
busy_tail=busy_head=free_head;
}
else
{
//把剛剛換進來的接在busy_tail后面
busy_tail->next=free_head;
busy_tail=free_head;
}
free_head=p; //下一個空頁面
}
}
printf("A.FIFO:%6.6f",1-(float)zhihuan/320);
return 0;
}
/*最近最久未使用算法least recently used*/
int LRU (int pf)
{
int min,minj,i,j,present_time; /*minj為最小值下標*/
initialize(pf);
present_time=0;
for(i=0;i<zllc;i++)
{
if(pl[page[i]].pfn==INVALID) /*頁面失效*/
{
zhihuan++;
if(free_head==NULL) /*無空閑頁面*/
{
min=32767; /*設置最大值*/
for(j=0;j<xy;j++) /*找出time的最小值*/
{
if(min>pl[j].time&&pl[j].pfn!=INVALID)
{
min=pl[j].time;
minj=j;
}
}
free_head=&pfc[pl[minj].pfn]; //騰出一個單元
pl[minj].pfn=INVALID;
pl[minj].time=0;
free_head->next=NULL;
}
pl[page[i]].pfn=free_head->pfn; //有空閑頁面,改為有效
pl[page[i]].time=present_time;
free_head=free_head->next; //減少一個free 頁面
}
else
{
pl[page[i]].time=present_time;//命中則增加該單元的訪問次數
present_time++;
}
}
printf("B.LRU:%6.6f",1-(float)zhihuan/320);
return 0;
}
/*最佳置換算法*/
int OPT(int pf)
{
int i,j, max,maxpage,dist[xy];
initialize(pf);
for(i=0;i<zllc;i++)
{
if(pl[page[i]].pfn==INVALID) /*頁面失效*/
{
zhihuan++;
if(free_head==NULL) /*無空閑頁面*/
{
for(j=0;j<xy;j++)
{
if(pl[j].pfn!=INVALID) //在主存中的頁面,即將找出一個被替換出去
dist[j]=32767;
else
dist[j]=0; //不在主存中的頁面
}
for(j=0;j<xy;j++)
{
if((pl[j].pfn!=INVALID)&&(dist[j]==32767))
{
dist[j]=j;
}
}
max=0;
for(j=0;j<xy;j++) //找最遠距離的,因為在主存中的最后一頁即是在虛存中的最后一頁
if(max<dist[j])
{
max=dist[j];
maxpage=j;
}
free_head=&pfc[pl[maxpage].pfn];
free_head->next=NULL;
pl[maxpage].pfn=INVALID;
}
pl[page[i]].pfn=free_head->pfn;
free_head=free_head->next;
}
}
printf("C.OPT:%6.6f\n",1-(float)zhihuan/320);
return 0;
}
int main()
{
int s,i;
srand((unsigned)time(NULL));
s=rand()%320; /*找出指令*/
for(i=0;i<zllc;i+=4) /*產生指令隊列*/
{
if(s<0||s>319)
{
printf("When i==%d,Error,s==%d\n",i,s);
exit(0);
}
a[i]=s; /*任選一指令訪問點m*/
a[i+1]=a[i]+1; /*順序執行一指令*/
a[i+2]=rand()%(a[i+1]+1);
a[i+3]=a[i+2]+1; /*順序執行一指令*/
s=rand()%(319-a[i+3])+a[i+3]+1;
if((a[i+2]>318)||(s>319))
printf("a[%d+2],a number which is :%d and s==%d\n",i,a[i+2],s);
}
for(i=0;i<zllc;i++) /*將指令序列變換成頁地址流*/
{
page[i]=a[i]/10; /*題目中的要求每頁大小10指令*/
offset[i]=a[i]%10;
}
for(i=4;i<=32;i++) /*用戶內存工作區從4個頁面到32個頁面*/
{
printf("%2d page frames:\n",i);
FIFO(i);
LRU(i);
OPT(i);
}
return 0;
}
