原創
最近操作系統實習,寫了先進先出算法(FIFO)的代碼來實現頁面置換。
題目闡述如下:
設計四:頁面置換
設計目的:
加深對請求頁式存儲管理實現原理的理解,掌握頁面置換算法。
設計內容:
設計一個程序,有一個虛擬存儲區和內存工作區,實現下述三種算法中的任意兩種,計算訪問命中率
(命中率=1-頁面失效次數/頁地址流長度)。附加要求:能夠顯示頁面置換過程。算法包括:先進先出的
算法(FIFO)、最少使用算法(LRU)、最近未使用算法(NUR)該系統頁地址流長度為320,頁面失效
次數為每次訪問相應指令時,該指令對應的頁不在內存的次數。 程序首先用srand()和rand()函數分別進
行初始化、隨機數定義和產生指令序列,然后將指令序列變換成相應的頁地址流,並針對不同的算法計算
出相應的命中率。通過隨機數產生一個指令序列。共320條指令,指令的地址按下述原則生成:
(1)50%的指令是順序執行的。
(2)25%的指令是均勻分布在前地址部分。
(3)25%的指令是均勻分布在后地址部分。
具體的實施方法如下:
在【0,319】的指令地址之間隨機選取一起點m。
順序執行一條指令,即執行地址為m+1的指令。
在前地址【0,m+1】中隨機選取一條指令並執行,該指令的地址為m’。
順序執行一條指令,其地址為m’+1。
在后地址【m’+2,319】中隨機選取一條指令並執行。
重復步驟(1)-(5),直到320次指令。
將指令序列變換為頁地址流。
設:
頁面大小為1KB。
用戶內存容量4頁到32頁。(動態變化)
用戶虛存容量為32KB。(32頁)
在用戶虛存中,按每K存放10條指令虛存地址,即320條指令在虛存中的存放方式為:
第0條~9條指令為第0頁(對應虛存地址為【0,9】)。
第10條~19條指令為第1頁(對應虛存地址為【10,19】)。
……
第310條~319條指令為第31頁(對應虛擬地址為【310,319】)。
按以上方式,用戶指令可組成32頁。
計算每種算法在不同內存容量下的命中率。
分頁管理是這樣的,將內存和作業分成大小相等的頁塊,作業中的每個頁塊在不需要被使用時存放在外存中(虛擬存儲區),
當需要使用時將其從外存調入內存頁塊中;根據題意,在外存中的頁面順序存儲着指令,需要執行哪一條指令就找到其對應的
頁面,若頁面已在內存則無需再操作,否則此頁面缺頁,需要將其調入內存,當內存塊未滿時,只需要直接將其插入內存塊中
若內存塊已滿,則需要調用先進先出算法淘汰出一個頁面(將其調回外存),再將此頁面調入。
首先通過 rand 函數和 srand 函數產生320條指令,計算每條指令對應的頁面很簡單,只需要將指令/10即可;得到頁地址流后
(頁地址流存放在數組中),從頭到尾訪問一遍頁地址流,每訪問一個頁面就判斷其是否已經在內存中,在無需操作,不在則
將其(使用FIFO)調入內存。
FIFO:在頁面缺頁並且內存塊不足時,只需要將內存塊中原先的頁面依次淘汰即可。
假設頁地址流為:1 2 3 5 4 3 8 11 12 6(內存塊大小為 3 )
1 2 3 進入內存
5 2 3 1被調出
5 4 3 2被調出
5 4 3 命中
5 4 8 3被調出(形成一個循環)
11 4 8 5被調出
11 12 8 4被調出
11 12 6 8被調出(形成一個循環)
只要為內存塊編號(不是為頁面編號),用一個變量(初值為1)作為指針,此變量指向的內存塊,就是被FIFO選中需要調出的
內存塊,調出后變量+1,當變量大於內存塊數時,再將其置為1(循環)。
#include<stdio.h> #include<time.h> #include<stdlib.h> #define max_page 10 //內存頁面數 int Page[320]={0}; //虛擬存儲區,存儲320條指令,32個頁面 int Page_flu[320]={0}; //存儲320個頁地址流 int count=0; //計算隨機產生的指令條數 double lack_page=0; //記錄缺頁數 int count_page=max_page; //計算隊列空頁面個數 int circle=1; //在隊列中循環指向被調出的進程 struct Memo{ //用結構體存儲內存頁面塊 int num; //給每個頁面編號,方便將其從隊列中找到並調出 int a; struct Memo *next; }; int Judge_Page(int value){ //輸入指令,返回指令對面的頁面號 return value/10; } int scan_queen(struct Memo *hear,int value){ //value代表頁面號,掃描隊列,缺頁返回0,否則返回1 struct Memo *move; move=hear->next; while(move!=NULL){ if(move->a==value){ return 1; } move=move->next; } return 0; } void print(struct Memo *hear){ //輸出內存頁面 struct Memo *move; move=hear->next; while(move!=NULL){ printf("%d ",move->a); move=move->next; } printf("\n"); } void insert(struct Memo *hear,int value,int ZL){ //將頁面value調入內存,ZL為對應指令 if(count_page>=1){ //內存頁面空間充足 struct Memo *move; move=hear->next; while(move->a!=-1){ move=move->next; } move->a=value; //將頁面調入 count_page--; printf("頁面 %d 被調入————對應指令為: %d \n",value,ZL); } else{ //內存空間不足,調出最先進入的頁面后,將頁面value后調入 struct Memo *move; move=hear->next; while(move->num!=circle){ //circle存儲的是需要調出的頁面編號 move=move->next; } printf("頁面 %d 被調出,頁面 %d 被調入————指令為: %d \n",move->a,value,ZL); move->a=value; //將頁面調入 circle++; if(circle==max_page+1){ //當circle>max_page+1時,最先進入的頁面為隊列首頁面 circle=1; } } print(hear); //調入后輸出內存隊列 } void FIFO(struct Memo *hear){ int i=0; for(i=0;i<=319;i++){ //循環掃描頁面 if( scan_queen(hear,Page_flu[i])==0){ //判斷是否缺頁 lack_page++; insert(hear,Page_flu[i],Page[i]); //缺頁將頁面調入內存 } else{ //不缺頁 printf("指令 %d 對應頁面 %d 已在內存\n",Page[i],Page_flu[i]); } //不缺頁無需操作 } } void Pro_Page(){ //形成頁地址流函數 int m=0; //在[0,319]的指令地址之間隨機選取一起點m m=rand()%320; Page[count]=m; count++; if(count==320){ return; } int m_=0; //在前地址[0,m+1]中隨機選取一條指令並執行 m_=rand()%(m+1); Page[count]=m_; count++; if(count==320){ return; } Page[count]=m_+1; count++; if(count==320){ return; } int m__=0; m__=(m_+2)+rand()%( 319-(m_+2)+1 ); //在后地址[m_+2,319]的指令地址之間隨機選取一條指令並執行 Page[count]=m__; count++; if(count==320){ return; } Pro_Page(); } void Flu(){ //將指令轉換為頁地址流 int i=0; for(i=0;i<=319;i++){ Page_flu[i]=Judge_Page( Page[i] ); } } int main(){ struct Memo Stu[max_page+1]; struct Memo *hear; hear=&Stu[0]; //************************************* int i=0; for(i=0;i<=max_page;i++){ //形成內存頁面隊列 if(i==max_page){ Stu[i].a=-1; Stu[i].next=NULL; Stu[i].num=i; break; } Stu[i].next=&Stu[i+1]; Stu[i].a=-1; Stu[i].num=i; } //************************************* srand(time(0)); //放在Pro_Page函數外面 Pro_Page(); //形成頁地址流 Flu(); //形成頁地址流 /* printf("頁地址流:\n"); for(i=0;i<=319;i++){ //輸出頁地址流 printf("%d ",Page[i]); if(i%3==0 && i!=0){ printf("\n"); } } printf("\n"); */ //************************************* FIFO(hear); printf("缺頁次數為: %0.0lf\n",lack_page); printf("命中率為:%lf\n",1-lack_page/320); return 0; }
(運行結果部分截圖)
11:33:47
2018-05-19
