写这个算法,就是一步一步调试出来的,花点功夫,其实原理比较简单,我使用的是链表。
中间有一些循环控制变量和条件需要琢磨以下,其他还好。
#define vpNum 10 //虚页块数
#define rpNum 3 //实页块数
ElemType arr[N] = { 7,0,1,2,0,3,4,2,3,0,3,2,1,2,0,1,7,0,1 };//页面引用串
完成这个分了三种情况:
第一种情况,虚页号和页面号引用串值相等且此时不在内存中
第二种情况,如果实页满了,进行页面置换
第三种情况,此时刻的页面号在内存中
完整代码:
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
#define vpNum 10 //虚页块数
#define rpNum 3 //实页块数
#define N 20 //页面引用串数目
#define MAX 100 //用于找最小访问时间的对比量,初值设置大一点
ElemType arr[N] = { 7,0,1,2,0,3,4,2,3,0,3,2,1,2,0,1,7,0,1 };//页面引用串
int count = 0; //记录一共多少次缺页
int sum = 1; //记录时刻
// 虚页数据结构
typedef struct VirtualPage {
ElemType virtualPage; //虚页号
ElemType realPage; //实页号
ElemType state; //状态
ElemType enterTime; //进入时间
ElemType accessTime; //访问时间
struct VirtualPage* next;
int len;
}VirtualPage, * VP;
// 实页数据结构
typedef struct RealPage {
ElemType realPage; //实页号
ElemType virtualPage; //虚页号
ElemType state; //状态
struct RealPage* next;
int len;
}RealPage, * RP;
//初始化虚页数据结构,尾插法
void init_VP(VP& vp) {
vp = (VP)malloc(sizeof(VirtualPage));
VP q, r = vp;
vp->len = vpNum;
for (int i = 0; i < vp->len; i++) {
q = (VP)malloc(sizeof(VirtualPage));
q->virtualPage = i;
q->realPage = -1;
q->state = 0;
q->enterTime = 0;
q->accessTime = 0;
r->next = q;
r = q;
}
r->next = NULL;
}
//初始化虚页数据结构,尾插法
void init_RP(RP& rp) {
rp = (RP)malloc(sizeof(RealPage));
RP q, r = rp;
rp->len = rpNum;
for (int i = 0; i < rp->len; i++) {
q = (RP)malloc(sizeof(RealPage));
q->realPage = i;
q->virtualPage = -1;
q->state = 0;
r->next = q;
r = q;
}
r->next = NULL;
}
//记录每个时刻为哪个页面上内存
void print(VP vp) {
printf("***************************************************\n");
printf("\n时刻%d:\n", sum++);
printf("页面%d装入内存\n", vp->virtualPage);
printf("%3d", vp->virtualPage);
printf("\t%3d", vp->realPage);
printf("\t%3d", vp->state);
printf("\t%3d", vp->enterTime);
printf("\t\t%3d\n", vp->accessTime);
}
//打印虚页 实页当前时刻状态
void showAns(VP vp, RP rp) {
vp = vp->next;
rp = rp->next;
printf("\n虚页号\t实页号\t状态\t加入时间\t访问时间\n");
while (vp != NULL) {
printf("%3d", vp->virtualPage);
printf("\t%3d", vp->realPage);
printf("\t%3d", vp->state);
printf("\t%3d", vp->enterTime);
printf("\t\t%3d\n", vp->accessTime);
vp = vp->next;
}
printf("\n实页号\t虚页号\t状态\n");
while (rp != NULL) {
printf("%3d", rp->realPage);
printf("\t%3d", rp->virtualPage);
printf("\t%3d\n", rp->state);
rp = rp->next;
}
printf("\n");
}
//LRU页面置换算法
void function(VP vp, RP rp, ElemType arr[]) {
//创建的是带头结点的链表,所以指向头结点的下一个节点为 0号 节点的值
VP v = vp->next;
RP r = rp->next;
bool flag = false;//控制缺页置换操作完成后 跳出循环
for (int i = 0; i < N; i++) {
while (v != NULL) {
flag = false;//每次循环都要重置flag
//第一种情况,虚页号和页面号引用串值相等且此时不在内存中
if (v->virtualPage == arr[i] && v->state == 0) {
//如果实页没满,直接装入内存
if (count < rpNum) {
v->state = 1;//状态置为1
while (r != NULL) {
if (r->state == 0) {//找一个实页中的空块
r->state = 1; //状态置为1
//修改虚页,实页中相关属性,与之对应
r->virtualPage = v->virtualPage;
v->realPage = r->realPage;
v->enterTime = i + 1;
v->accessTime = i + 1;
flag = true;//标志找到一个空块
print(v);
showAns(vp, rp);
count++; //缺页次数加一
break;
}
r = r->next;//没找到符合要求的节点,继续向下找
}
}
//第二种情况,如果实页满了,进行页面置换
else {
VP temp = vp->next;
VP t = (VP)malloc(sizeof(VirtualPage));//临时节点,用来找到访问时间最小的节点
t->accessTime = MAX;
while (temp != NULL) {
//比大小
if (temp->accessTime < t->accessTime && temp->state == 1) {
t = temp;
}
temp = temp->next;
}
v->state = 1;//置换的页面状态改为1
t->state = 0;//被置换的页面状态改回0
while (r != NULL) {
//通过虚页的实页号找到实页中对应的实页块,并修改对应参数
if (t->realPage == r->realPage && r->state == 1) {
v->realPage = t->realPage;
t->realPage = -2;//表示装入过内存
v->enterTime = i + 1;
v->accessTime = i + 1;
r->virtualPage = v->virtualPage;
flag = true;//标志替换成功
print(v);
showAns(vp, rp);
count++;
break;
}
r = r->next;
}
}
}
//第三种情况,此时刻的页面号在内存中
else if (v->virtualPage == arr[i] && v->state == 1) {
v->accessTime = i + 1;//修改访问时间
flag = true;//标志操作完成
print(v);
showAns(vp, rp);
break;
}
if (flag) break;//三种情况中,任一种成功就直接判断下一个页面号,不成功再判断下一个虚页块是否满足要求
v = v->next;
}
//用于回到链表头。进行重新比对
v = vp->next;
r = rp->next;
}
}
int main() {
VP vp;
init_VP(vp);
RP rp;
init_RP(rp);
function(vp, rp, arr);
showAns(vp, rp);
int s = count + 1;
printf("\n该访问序列的缺页率为:%.2f%c\n\n\n\n",(s*1.0/N)*100,'%');
return 0;
}