操作系统实验:页面置换算法——FIFO、LRU 代码实现

FIFO(First-In-First-Out)

        最简单的页面置换算法是FIFO。在分配内存页面数(AP)小于进程页面数(PP)时,最先运行的AP个页面放入内存;当内存分配页面被占满时,如果又需要处理新的页面,则将原来放的内存中的AP个页中最先进入的调出(FIFO),再将新页面放入;所使用的内存页面构成一个队列。

实验要求:

1)初始化。设置两个数组page[ap]pagecontrol[pp]分别表示进程页面数和内存分配的页面数,并产生一个随机数序列main[total_instruction](这个序列由page[ap]的下标随机构成)表示待处理的进程页面顺序,diseffect0

2)看main[]中是否有下一个元素,若有,就由main[]中获取该页面下标,并转(3),如果没有则转(7)。

3)如果该页已在内存中,就转(2),否则转(4),同时未命中的diseffect1

4)观察pagecontrol是否占满,如果占满则须将使用队列(在第(6)步中建立的)中最先进入的(就是队列的第一个单元)pagecontrol单元“清干净”,同时将page[]单元置为“不在内存中”。

5) 将该page[]pagecontrol[]建立对应关系(可以改变pagecontrol[]的标志位,也可以采用指针链接,总之至少要使对应的pagecontrol单元包含两个信息:一是它被使用了,二是哪个page[]单元使用的。page[]单元也包含两个信息:对应的pagecontrol单元号和本page[]单元已在内存中)。

 (6) 将用到的pagecontrol置入使用队列(这里的队列是一种FIFO的数据结构),返回(2)。

(7) 显示计算1-diseffect / total_instruction*100%,完成。

程序框图: 

 

代码实现: 

#include<stdio.h>
#include<stdlib.h> 
#include<time.h>

#define ProcessPageNum 10       //进程页面数
#define MemPageNum 5            //内存页面数
#define totalInstruction 100    //引用次数
int diseffect = 0;              //缺页错误数
/*定义进程页面结构体*/
struct pageNode{
    int pageID;             //进程页面ID
    int flag;               //1表示页面在内存中,0表示不在
    int pagecontrolIndex;   //所在内存页面ID 不在内存中时值为-1
};
/*定义内存页面结点*/
struct pagecontrolNode{
    int pagecontrolID;      //内存页面ID
    int flag;               //1表示被占用,0表示空闲
    int pageIndex;          //所加载进程页面ID
    struct pagecontrolNode *next;
};
/*定义FIFO队列*/
struct pagecontrolQueue{
    struct pagecontrolNode *front;
    struct pagecontrolNode *rear;
};
/*返回队首结点*/
struct pagecontrolNode* getFront(struct pagecontrolQueue *queue){
    return queue->front;
}
/*入队*/
void inQueue(struct pagecontrolQueue *queue,struct pagecontrolNode *p){
    if(queue->front == NULL){
        queue->front = p;
        queue->rear = p;
    }else{
        queue->rear->next = p;
        queue->rear = p;
        queue->rear->next = NULL;
    }
}
/*出队*/
void outQueue(struct pagecontrolQueue *queue){
    if(queue->front == NULL) exit(-1);
    else{
        queue->front = queue->front->next;
        if(queue->front == NULL) queue->rear = NULL;
    }
}
/*判断内存页面是否被占满 1为满*/
int isFull(struct pagecontrolNode *pagecontrol[MemPageNum]){
    int i = 0;
    for (i;i < MemPageNum;i++){
        if(pagecontrol[i]->flag == 0) return 0;
    }
    return 1;
}
/*初始化page数组*/
void initPage(struct pageNode *page[ProcessPageNum]){
    int i = 0;
    for(i;i < ProcessPageNum;i++){
        page[i] = (struct pageNode*)malloc(sizeof(struct pageNode)); 
        page[i]->flag = 0;
        page[i]->pageID = i;
        page[i]->pagecontrolIndex = -1;
    }
}
/*初始化pagecontrol数组*/
void initPagecontrol(struct pagecontrolNode *pagecontrol[MemPageNum]){
    int i = 0;
    for(i;i < MemPageNum;i++){
        pagecontrol[i] = (struct pagecontrolNode*)malloc(sizeof(struct pagecontrolNode)); 
        pagecontrol[i]->pagecontrolID = i;
        pagecontrol[i]->flag = 0;
        pagecontrol[i]->pageIndex = -1;
        pagecontrol[i]->next = NULL;
    }
}

int main(){
    struct pageNode *page[ProcessPageNum];
    struct pagecontrolNode *pagecontrol[MemPageNum];
    initPage(page);
    initPagecontrol(pagecontrol);
    /*初始化队列*/
    struct pagecontrolQueue *queue;
    queue = (struct pagecontrolQueue*)malloc(sizeof(struct pagecontrolQueue));
    queue->front = NULL;
    queue->rear = NULL; 
    /*构造随机序列buffer*/
    int buffer[totalInstruction];
    int i = 0;
    srand((unsigned)time(NULL));
    for(i;i < totalInstruction;i++){
        buffer[i] = rand() % ProcessPageNum;
    }
    int j = 0;
    int index = 0;  //当前内存页面下标
    for(j;j < totalInstruction;j++){
        if(page[buffer[j]]->flag == 0){ //若当前页面不在内存中
            diseffect++;                //缺页错误数加1
            page[buffer[j]]->flag = 1;
            if(isFull(pagecontrol)){    //若内存已满,则需要页面置换
                page[queue->front->pageIndex]->flag = 0;    //队首页面被换出
                page[queue->front->pageIndex]->pagecontrolIndex = -1;
                queue->front->pageIndex = page[buffer[j]]->pageID; //存入当前页面
                struct pagecontrolNode *temp;
                temp = getFront(queue);
                outQueue(queue);        //队首页面出队列
                inQueue(queue,temp);    //修改后再加入队列
            }else{                      //如果内存未满,则按照先后顺序存入
                pagecontrol[index]->flag = 1;
                pagecontrol[index]->pageIndex = page[buffer[j]]->pageID;
                page[buffer[j]]->pagecontrolIndex = pagecontrol[index]->pagecontrolID;
                inQueue(queue, pagecontrol[index]);
                index++;
            }
        }
    }
    double rightRate = (1.0 - ((double)diseffect / (double)totalInstruction))*100;
    printf("错误次数%d\n",diseffect);
    printf("正确率%.2f%%\n",rightRate);
}

LRU(Least-Recent-Used algorithm)

        计数器实现法:在最简单的情况下,为每个页表条目关联一个使用时间域,并为CPU添加一个逻辑时钟或计数器。每次内存引用都会递增时钟;且每当进行页面引用时,时钟寄存器的内容会复制到相应页面的页表条目的使用时间域。这样我们总是找到每个页面最后被引用的时间,便可以置换拥有最小使用时间的页面。

实验要求:

(1) 初始化。设置两个数组page[ap]pagecontrol[pp]分别表示进程页面数和内存分配的页面数,并产生一个随机数序列main[total_instruction](这个序列由page[ap]的下标随机构成)表示待处理的进程页面顺序,diseffect0

(2) 看序列main[]中是否有下一个元素,如果有,就由main[]中获取该页面下标,并转(3),如果没有则转(6)。

(3) 如果该page[]单元在内存中便改变页面属性,使它保留“最近使用”的信息,转(2),否则转(4),同时diseffect1

(4) 看是否有空闲页面,如果有,就返回页面指针,并转到(5),否则,在内存页面d其“清干净”,并返回该页面指针。

(5) 在需处理的page[]与(4)中得到的pagecontrol[]之间建立联系,同时让对应的page[]单元保存“最新使用”的信息,转(2)。

         (6) 如果序列处理完成,就输出计算1-diseffect / total_instruction*100%的结果

程序框图: 

 

 代码实现:

#include<stdio.h>
#include<stdlib.h> 
#include<time.h>
/*实现方法与FIFO算法大同小异,无需定义队列,而是用计数器实现选择牺牲帧*/
#define ProcessPageNum 10       //进程页面数
#define MemPageNum 5            //内存页面数
#define totalInstruction 100    //引用次数
int diseffect = 0;              //缺页错误数
/*定义进程页面结构体*/
struct pageNode{
    int pageID;             //进程页面ID
    int flag;               //1表示页面在内存中,0表示不在
    int pagecontrolIndex;   //所在内存页面ID 不在内存中时值为-1
    int useTime;            //最后被引用时间
};
/*定义内存页面结点*/
struct pagecontrolNode{
    int pagecontrolID;      //内存页面ID
    int flag;               //1表示被占用,0表示空闲
    int pageIndex;          //所加载进程页面ID
};
/*初始化page数组*/
void initPage(struct pageNode *page[ProcessPageNum]){
    int i = 0;
    for(i;i < ProcessPageNum;i++){
        page[i] = (struct pageNode*)malloc(sizeof(struct pageNode)); 
        page[i]->flag = 0;
        page[i]->pageID = i;
        page[i]->pagecontrolIndex = -1;
        page[i]->useTime = 0;
    }
}
/*初始化pagecontrol数组*/
void initPagecontrol(struct pagecontrolNode *pagecontrol[MemPageNum]){
    int i = 0;
    for(i;i < MemPageNum;i++){
        pagecontrol[i] = (struct pagecontrolNode*)malloc(sizeof(struct pagecontrolNode)); 
        pagecontrol[i]->pagecontrolID = i;
        pagecontrol[i]->flag = 0;
        pagecontrol[i]->pageIndex = -1;
    }
}
/*判断内存页面是否被占满 1为满*/
int isFull(struct pagecontrolNode *pagecontrol[MemPageNum]){
    int i = 0;
    for (i;i < MemPageNum;i++){
        if(pagecontrol[i]->flag == 0) return 0;
    }
    return 1;
}
/*找到内存中页面最后引用时间最小的page结点并返回*/
struct pageNode* findMinUseTime(struct pageNode *page[ProcessPageNum]){
    struct pageNode *temp;
    temp = (struct pageNode*)malloc(sizeof(struct pageNode)); 
    temp->useTime = totalInstruction;
    int i = 0;
    for(i;i < ProcessPageNum;i++){
        if(page[i]->useTime < temp->useTime && page[i]->flag == 1){
            temp = page[i];
        }
    }
    return temp;
}
int main(){
    struct pageNode *page[ProcessPageNum];
    struct pagecontrolNode *pagecontrol[MemPageNum];
    initPage(page);
    initPagecontrol(pagecontrol);
    /*构造随机序列buffer*/
    int buffer[totalInstruction];
    int i = 0;
    srand((unsigned)time(NULL));
    for(i;i < totalInstruction;i++){
        buffer[i] = rand() % ProcessPageNum;
    }
    int j = 0;
    int timer = 0;  //设置计数器
    int index = 0;  //当前内存页面下标
    for(j;j < totalInstruction;j++){
        timer++;    //计数器递增
        page[buffer[j]]->useTime = timer;
        if(page[buffer[j]]->flag == 0){ //若当前页面不在内存中
            diseffect++;                //缺页错误数加1
            page[buffer[j]]->flag = 1;
            if(isFull(pagecontrol)){    //若内存已满
                struct pageNode *temp = findMinUseTime(page);   //找到将被置换的页面
                temp->flag = 0;
                temp->useTime = 0;
                pagecontrol[temp->pagecontrolIndex]->pageIndex = page[buffer[j]]->pageID;   //修改pagecontrol数组
                page[buffer[j]]->pagecontrolIndex = pagecontrol[temp->pagecontrolIndex]->pagecontrolID; //修改page数组
                temp->pagecontrolIndex = -1;
            }else{                      //若内存未满,则按顺序存入
                pagecontrol[index]->flag = 1;
                pagecontrol[index]->pageIndex = page[buffer[j]]->pageID;
                page[buffer[j]]->pagecontrolIndex = pagecontrol[index]->pagecontrolID;
                index++;
            }
        }
    }
    double rightRate = (1.0 - ((double)diseffect / (double)totalInstruction))*100;
    printf("错误次数%d\n",diseffect);
    printf("正确率%.2f%%\n",rightRate);
}

参考资料:

《操作系统概念(第九版)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值