先進先出算法(FIFO)——頁面置換


原創


最近操作系統實習,寫了先進先出算法(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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM