实 验 报 告
学生姓名 |
**,** |
学号 |
****** |
指导老师 |
*** |
实验地点 |
实验时间 |
班级 |
***** |
虚拟存储器管理
4学时
虚拟存储器作为现代操作系统中存储器管理的一项重要技术,实现了内存扩充功能。但该功能并非是从物理上实际地扩大内存的容量,而是从逻辑上实现对内存容量的扩充,让用户所感觉到的内存容量比实际内存容量大得多。于是便可以让比内存空间更大的程序运行,或者让更多的用户程序并发运行。这样既满足了用户的需要,又改善了系统的性能。
假定某进程共有8页,且系统为之分配了三个物理块,并有以下页面调度序列∶7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1
使用以下置换算法:最佳置换算法(OPT)、先进先出置换算法(FIFO)、最近最少用置换算法(LRU)。
计算并输出:页面置换情况和缺页率。
最佳置换算法输出效果如下:
OPT:f=0.45 7x,0x,1x,2x,0,3x,0,4x,2,3 ,0x,3,2,1x,2,0,1,7x,0,1 |
/**-------------------------------------------------实验开始--------------------------------------------------*/
1、最佳(OPT)页面置换算法:
(3)代码:
#include
int num[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };
int A[3] = { -1, -1, -1 };
int physicalBlock[3] = { -1, -1, -1 }; // 3个物理块
bool OPT(int index) {
int i; //标识物理块号
for (i = 0; i < 3; i++) {
if (A[i] == -1) //判断该物理块是否为空物理块
break; //如果当前物理块为空物理块,则证明后面的物理块都为空物理块,需要装入页面。
if (physicalBlock[i] == num[index]) // 判断页面是否在内存中
return true;
}
if (i == 3) { //没有空物理块,需要替换页面
int flag = 0; // 标记有几个物理块的页面在随后的访问中被访问;
for (int m = index + 1; m < 20; m++) {
if (flag == 2) {
break;
}
for (int n = 0; n < 3; n++) { // 遍历物理块
if (num[m] == physicalBlock[n]) { // 该物理块的页面会在随后的访问中被访问
if (A[n] != 0) {
A[n] = 0;
flag++;
}
break;
}
}
}
for (int i = 0; i < 3; i++) {
if (A[i] != 0) {
physicalBlock[i] = num[index]; // 替换出该物理块中的页面
A[i] = 1; // 将标记改成有页面
}
A[i] = 1;
}
return false;
} else {
physicalBlock[i] = num[index]; //第i个物理块中放入页面
A[i] = 1;
return false;
}
}
void OPT1() {
int N = 0; //页面置换次数
for (int i = 0; i < 20; i++) {
bool b = OPT(i);
if (b == true) {
printf("%d ", num[i]);
}
if (b == false) { //页面发生了置换
printf("%dx ", num[i]);
N++;
}
}
double d = (double)N / 20 ;
printf("\nOPT:f=%.2f", d);
}
int main() {
OPT1();
}
(4)输出截图:
2.先进先出(FIFO)页面置换算法:
(1)流程图
(3)代码:
①主函数
#include
#include
#include "Queue.h"
using namespace std;
void FIFO(int order[20],int visitied[20])
{
cout<<"先进先出置换算法输出效果如下:"< SqQueue Q;InitQueue(Q); //创建并初始化队列 int i,j; float flag=0,per; //缺页次数与缺页率 for(i=0;i<20;i++) //所要调度序列长度 { if(Queue_FInd(Q,order[i])) //判断是否缺页 {//不缺 visitied[i]=1; continue; } else {//缺页 flag+=1;//缺页次数+1 if(QueueFull(Q)) //判断物理块是否有剩余 {//物理块用光了 DeQueue(Q,j); //FIFO //队头出队 EnQueue(Q,order[i]); //队尾进队 } else //使用剩余物理块 {//物理块还有剩的 EnQueue(Q,order[i]); //入队 } visitied[i]=0; } } per=flag/20; printf("FIFO:f=%.2f\n",per); } int main() { int Order[20]={7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1}; int visitied[20]; //为保持输出与规定的一样,现创建一个数组;缺页置0,不缺置1; FIFO(Order,visitied); for(int i=0;i<20;i++) { if(visitied[i]==0) { cout< } else { cout< } } return 0; } ②头文件——Queue.h #include #include using namespace std; #define MAXSIZE 4 //定义物理块数。实际使用中会少用一个空间来实现循环 队列 #define OK 1 #define ERROR 0 #define OVERFLOW -1 typedef int Status; typedef struct { int *base; ///顺序表要加*号,要给空间,存基地址 //or int data[MAXSIZE]; int Front; int Rear; }SqQueue; ///初始化 Status InitQueue(SqQueue &Q) { Q.base=new int[MAXSIZE]; if(!Q.base) exit(OVERFLOW); Q.Front=Q.Rear=0; return OK; } ///入队 Status EnQueue(SqQueue &Q,int e) { if((Q.Rear+1)%MAXSIZE==Q.Front) return OVERFLOW; Q.base[Q.Rear]=e; Q.Rear=(Q.Rear+1)%MAXSIZE; ///防溢出 return OK; } ///出队 Status DeQueue(SqQueue &Q,int &E) { if(Q.Front==Q.Rear) return ERROR; E=Q.base[Q.Front]; Q.Front=(Q.Front+1)%MAXSIZE; return OK; } ///求队列长度 Status QueueLength(SqQueue Q) { return (Q.Rear-Q.Front+MAXSIZE)%MAXSIZE; } ///get head Elem Status GetHead(SqQueue Q) { if(Q.Front!=Q.Rear) { return Q.base[Q.Front]; //队头指针不变 } } ///判空 Status QueueEmpty(SqQueue Q) { if(Q.Front==Q.Rear) return OK; else return ERROR; } ///判满 bool QueueFull(SqQueue Q) { if((Q.Rear+1)%MAXSIZE==Q.Front) return true; else return false; } ///遍历队列查找 bool Queue_FInd(SqQueue Q,int E) { int i,head,rear; head=Q.Front;rear=Q.Rear; /*if(QueueEmpty(Q)) { cout<<"队列为空"; return false; }*/ for(i=0;i { if(Q.base[head]==E) { return true; } head=(head+1)%MAXSIZE; } if(i==QueueLength(Q)) { return false; } } ///打印队列 int Queue_Printf(SqQueue Q) { int i,head; head=Q.Front; if(QueueEmpty(Q)) { cout<<"队列为空"; return ERROR; } for(i=0;i { cout< head=(head+1)%MAXSIZE; } } (4)输出截图: 3.最近最久未使用(LRU)页面置换算法: (1)流程图 (2)算法分析和描述: (3)代码:(头文件——Queue.h 同上 此处略) #include #include #include "Queue.h" using namespace std; ///交换数值 void Swap(int &a,int &b) { int t; t=a; a=b; b=t; } /**-----改变队列内元素顺序----*/ void Change_QElem(SqQueue &Q,int E) { int L,Locate2; L=(Q.Front+QueueLength(Q)-1)%MAXSIZE; //确定队尾元素的位置 Locate2=(Q.Front+1)%MAXSIZE; //确定队头后一个元素的位置 if(Q.base[L]==E);//队尾元素是最新页,无需变换队列元素顺序 else {//队尾元素不是最新页 if(L==Locate2) //队列只有两个元素时 { Swap(Q.base[L],Q.base[Q.Front]); //两个元素进行交换 } else //队列有三个元素时即队满,有两种情况:①队头是最新页②队头后一个元素是最新页 { if(Q.base[Q.Front]==E) //① { //方法一:利用第四个空间 Q.base[Q.Rear]=Q.base[Q.Front]; Q.base[Q.Front]=NULL; Q.Front=(Q.Front+1)%MAXSIZE; Q.Rear=(Q.Rear+1)%MAXSIZE; //方法二:两次交换 /*Swap(Q.base[Q.Front],Q.base[Locate2]); Swap(Q.base[Locate2],Q.base[L]);*/ } else //② { Swap(Q.base[L],Q.base[Locate2]); //两个元素进行交换 } } } } /**-------LRU--------*/ void LRU(int Order[20],int visited[20]) { int i=0,E; float flag=0,per; //定义缺页次数与缺页率 SqQueue Q;InitQueue(Q); for(i=0;i<20;i++) { if(Queue_FInd(Q,Order[i])) //判断是否缺页 {//不缺页 visited[i]=1; Change_QElem(Q,Order[i]); ///按最近最久来重新排序队列内元素 } else {//缺页 flag+=1; //缺页次数+1 if(QueueFull(Q)) //判断物理块是否有剩余 {//无剩余 DeQueue(Q,E); //队头(最近最久未使用的页)出队 EnQueue(Q,Order[i]); } else {//有剩余 EnQueue(Q,Order[i]); } visited[i]=0; } } per=flag/20; cout<<"最佳置换算法输出效果如下"< printf("LRU:f=%.2f\n",per); } int main() { int Order[20]={7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1}; int visitied[20]; //为保持输出与规定的一样,现创建一个数组;缺页置0,不缺置1; LRU(Order,visitied); for(int i=0;i<20;i++) { if(visitied[i]==0) {