实验八 页面置换模拟程序设计
一、实验目的
1、通过软件模拟页面置换过程,加深对请求页式存储管理实现原理的理解
2、理解和掌握OPT、FIFO和LRU三种页面置换算法,深入分析三者之间的优缺点。
二、实验环境
硬件环境:计算机一台,局域网环境;
软件环境: Windows或Linux操作系统, C语言编程环境。
三、实验内容和步骤
参考设计思路
(1)重要数据结构
① 页表数据结构
typedef struct
{
int vmn;
int pmn;
int exist;
int time;
}vpage_item;
vpage_item page_table[VM_PAGE];
页表是虚地址向物理地址转换的依据,包含虚页号所对应的实页号,是否在物理内存中。
页表中增加了一个time项,用于替换算法选择淘汰页面,在不同的替换算法中,time含义不一样。
在LRU算法中,time为最近访问的时间。该虚页每访问一次,time置为当前访问时刻,淘汰页面时,淘汰time值最小的,即最久没有被使用的。
在FIFO算法中,time为该虚页进入内存的时间。只有当该虚页从外存进入内存时,才置该标志。淘汰页面时,淘汰time值最小的,即最早进入内存的虚页。
在OPT算法中,time没有任何意义。
② 物理页位图数据结构
vpage_item * ppage_bitmap[PM_PAGE];
物理页位图是用于记录物理页是否被使用,用于物理页内存的分配。正常情况下是一个数组,元素值为0时,代表相应物理页没有装入任何虚页,值为1时,代表该物理页装入虚页。但为方便替换算法检索要替换出去的虚页,数组的每个元素值为当前放在该物理页的页表项的指针。若值为NULL,则表示该物理页没有被占用,当值不为NULL时,表示正在占用该物理页的虚页。
③指令相关数据结构
//每条指令信息
typedef struct{
int num;
int vpage;
int offset;
int inflow;
}instr_item;
//指令数组
instr_item instr_array[TOTAL_INSTR];
//指令流数据结构
struct instr_flow{
instr_item *instr;
struct instr_flow *next;
};
//指令流头数据结构
struct instr_flow_head{
int num;
struct instr_flow *next;
};
struct instr_flow_head iflow_head;
每条指令包括指令号、该指令所属虚页及页内偏移(这两项可以根据指令号计算出来,增加这两项是为了方便编程)。inflow是一个辅助项,用于构建指令流。
本题要求,按照规则生成的指令流中,应包含所有的共320条指令。但每次随机生成的指令号,可能已在指令流中,因此最终指令流中的指令数可能远远超过320条指令。
设置inflow的目的是为了便于统计是否320条指令均已加入到指令流中。在该条指令加入到指令流中时,如果inflow为0,表示该指令尚未在指令流中,则统计数加1;如果inflow为1,表示该指令已经加入过指令流,该指令虽然再次加入指令流,但统计数不增加。这样,当统计计数为320时,表示所有的指令均已加入到指令流中。
struct instr_flow为指令流数据结构,struct instr_flow_head始终指向指令流的头,其中num用于指令流中指令数量计数,用于计算缺页率。
(2)主程序,如下图所示。
(3)指令流生成流程
指令流的生成按照实验要求生成,其算法流程如下图所示。
(4)物理内存分配流程
物理内存分配时,需要根据当前置换算法选择淘汰页面。其算法流程下图所示。
(5)运行流程图,如下图所示。
(6)三种置换算法
①OPT算法:在当前指令的后续指令流中,寻找已在内存中的虚页,哪个最远才被使用,反过来,如果先找到最近三个(物理页面总数为4)也在内存中的虚页,则剩下的那个虚页肯定就是最远才被使用的虚页,该虚页被淘汰,其物理内存分配给当前指令所在的虚页。
②FIFO算法:在已在物理内存中的虚页中,寻找time最小的虚页(最早进入物理内存的虚页),该虚页即是被淘汰的虚页。
③LRU算法:思想同FIFO算法,但time最小的虚页含义是最久没有被使用的虚页。
在这三种置换算法中,OPT的算法稍微复杂一些,下图给了该算法的程序流程图。
程序代码
#include <iostream>
#define VM_PAGE 32 /*假设每个页面可以存放10条指令,则共有32个虚页*/
#define PM_PAGE 4 /*分配给作业的内存块数为4*/
#define TOTAL_INSTR 320 /*320条指令*/
using namespace std;
int instr_count = 0;
typedef struct
{int vmn; //虚页号int pmn;//实页号int exist;//是否存在内存int time;//时间,作为置换依据
}vpage_item;
vpage_item page_table[VM_PAGE];//虚页表
vpage_item* ppage_bitmap[PM_PAGE]; //实页表//每条指令信息
typedef struct {int num;//指令号int vpage;//虚页号int offset;//页内偏移int inflow;//是否在指令流中
}instr_item;//指令数组
instr_item instr_array[TOTAL_INSTR];//指令流数据结构
struct instr_flow {instr_item* instr;struct instr_flow* next;
};
//指令流头数据结构
struct instr_flow_head {int num = 0;//用于指令流中指令数量计数struct instr_flow* next;
};
struct instr_flow_head iflow_head;void Init_PTable() //页表初始化
{for (int i = 0; i < VM_PAGE; i++){page_table[i].vmn = i + 1; //虚页号page_table[i].pmn = -1; //实页号page_table[i].exist = 0;page_table[i].time = -1;}for (int i = 0; i < PM_PAGE; i++){ppage_bitmap[i] = NULL;}
}void Init_Instr()
{int n, count = 1, i = 0,m;for (i = 0; i < TOTAL_INSTR; i++){instr_array[i].num = i;if (count % 10 != 0)m = count / 10 + 1;elsem = count / 10;instr_array[i].vpage = m;instr_array[i].offset = count - (m - 1) * 10 - 1;instr_array[i].inflow = 0;count++;}srand((unsigned)time(NULL));instr_flow* p_instr_flow = new instr_flow;iflow_head.next = p_instr_flow;while(true){n = rand() % TOTAL_INSTR;if (instr_array[n].inflow == 0) {instr_array[n].inflow = 1;iflow_head.num++;}instr_count++;p_instr_flow->instr = new instr_item;p_instr_flow->instr = instr_array + n;p_instr_flow->next = new instr_flow;printf("%d\t%d\t%d\n", p_instr_flow->instr->num, p_instr_flow->instr->vpage, p_instr_flow->instr->offset);if (iflow_head.num == TOTAL_INSTR) {//所有指令均位于指令流中p_instr_flow->next = NULL;break; }p_instr_flow = p_instr_flow->next;}
}
void FIFO()/*FIFO页面置换算法*/
{int k = 0;int i;int missing_page_count = 0;int current_time = 0;instr_flow* p_instr_flow = new instr_flow;p_instr_flow = iflow_head.next;while (p_instr_flow!=NULL){if (page_table[p_instr_flow->instr->vpage - 1].exist == 0){missing_page_count++;if (k < PM_PAGE){if (ppage_bitmap[k] == NULL) /*找到一个空闲物理块*/{ppage_bitmap[k] = &page_table[p_instr_flow->instr->vpage - 1];ppage_bitmap[k]->exist = 1;ppage_bitmap[k]->pmn = k;ppage_bitmap[k]->time = current_time;k++;}}else{int temp = ppage_bitmap[0]->time; /*记录物理块中作业最早到达时间*/int j = 0; /*记录应当被替换的物理块号*/for (i = 0; i < PM_PAGE; i++) /*寻找最早到达的作业*/{if (ppage_bitmap[i]->time < temp){temp = ppage_bitmap[i]->time;j = i;}}ppage_bitmap[j]->exist = 0;ppage_bitmap[j] = &page_table[p_instr_flow->instr->vpage - 1]; /*更新页表项*/ppage_bitmap[j]->exist = 1;ppage_bitmap[j]->pmn = j;ppage_bitmap[j]->time = current_time;}}current_time++;p_instr_flow = p_instr_flow->next;}printf("FIFO算法缺页次数为:%d\t缺页率为:%f\t置换次数为:%d\t置换率为:%f\n", missing_page_count, missing_page_count / (float)instr_count, missing_page_count - 4, (missing_page_count - 4) / (float)instr_count);
}
void LRU()
{int k = 0;int i;int missing_page_count = 0;int current_time = 0;instr_flow* p_instr_flow = new instr_flow;//bool isleft = true; /*当前物理块中是否有剩余*/p_instr_flow = iflow_head.next;while (p_instr_flow != NULL){if (page_table[p_instr_flow->instr->vpage - 1].exist == 0)/*当前指令不存在物理块中*/{missing_page_count++;if (k < PM_PAGE){if (ppage_bitmap[k] == NULL) /*找到一个空闲物理块*/{ppage_bitmap[k] = &page_table[p_instr_flow->instr->vpage - 1];ppage_bitmap[k]->exist = 1;ppage_bitmap[k]->pmn = k;ppage_bitmap[k]->time = current_time;k++;}}else{int temp = ppage_bitmap[0]->time; /*记录物理块中作业最早到达时间*/int j = 0; /*记录应当被替换的物理块号*/for (i = 0; i < PM_PAGE; i++)/*找到时间最小的物理块,也就是最久未使用的*/{if (ppage_bitmap[i]->time < temp){temp = ppage_bitmap[i]->time;j = i;}}ppage_bitmap[j]->exist = 0;ppage_bitmap[j] = &page_table[p_instr_flow->instr->vpage - 1]; /*更新页表项*/ppage_bitmap[j]->exist = 1;ppage_bitmap[j]->pmn = j;ppage_bitmap[j]->time = current_time;}}else/*当前指令在物理块中,时间更新*/{page_table[p_instr_flow->instr->vpage - 1].time = current_time;}current_time++;p_instr_flow = p_instr_flow->next;}printf("LRU算法缺页次数为:%d\t缺页率为:%f\t置换次数为:%d\t置换率为:%f\n", missing_page_count, missing_page_count / (float)instr_count, missing_page_count - 4, (missing_page_count - 4) / (float)instr_count);
}void OPT()
{int k = 0;int missing_page_count = 0;int current_time = 0;instr_flow* p_instr_flow = new instr_flow;p_instr_flow = iflow_head.next;while (p_instr_flow != NULL) {if (page_table[p_instr_flow->instr->vpage - 1].exist == 0) {missing_page_count++;if (k < PM_PAGE){if (ppage_bitmap[k] == NULL) /*找到一个空闲物理块*/{ppage_bitmap[k] = &page_table[p_instr_flow->instr->vpage - 1];ppage_bitmap[k]->exist = 1;ppage_bitmap[k]->pmn = k;ppage_bitmap[k]->time = current_time;k++;}}else {int used[VM_PAGE] = { 0 };/*记录哪些虚页已经使用*/int i;instr_flow* pp_instr_flow = p_instr_flow->next;int count = 0;/*便利剩余指令*/for (pp_instr_flow; pp_instr_flow != NULL; pp_instr_flow = pp_instr_flow->next) {if (page_table[pp_instr_flow->instr->vpage - 1].exist == 1) {used[page_table[pp_instr_flow->instr->vpage - 1].vmn - 1] = 1;}for (i = 0; i < VM_PAGE; i++) {if (used[i] == 1) {count++;}}if (count == 3) {break;}}for (i = 0; i < PM_PAGE; i++) {if (used[ppage_bitmap[i]->vmn - 1] == 0) {ppage_bitmap[i]->exist = 0;ppage_bitmap[i] = &page_table[p_instr_flow->instr->vpage - 1];ppage_bitmap[i]->exist = 1;ppage_bitmap[i]->pmn = i;ppage_bitmap[i]->time = current_time;}}}}current_time++;p_instr_flow = p_instr_flow->next;}printf("OPT算法缺页次数为:%d\t缺页率为:%f\t置换次数为:%d\t置换率为:%f", missing_page_count, missing_page_count / (float)instr_count, missing_page_count - 4, (missing_page_count - 4) / (float)instr_count);
}
int main()
{Init_PTable();cout << "指令流如下:" << endl;printf("-----------------------------------------------\n");printf("指令号\t所在页\t页内位移\n");printf("-----------------------------------------------\n");Init_Instr();printf("-----------------------------------------------\n");cout << "共计" << instr_count << "条指令" << endl;cout << endl << endl;FIFO();Init_PTable();LRU();Init_PTable();OPT();return 0;}
实验结果
实验分析
①分析实验结果产生的原因,总结从实验观察到的结果,分析三种置换算法的缺页率的差异。
FIFO算法每次先替换最先进入的页面,LRU算法每次先替换最近最久未使用的页面,OPT算法每次先替换将来最长时间内不再被访问的页面。所以FIFO算法的置换率相对较大,而LRU算法考虑到了程序的局部性原理,相对较小,OPT算法也相对较小。
②结合操作系统课程中讲授的原理,写出本次实验的心得体会。
FIFO算法置换最先调入内存的页面,即置换在内存中驻留时间最久的页面。按照进入内存的先后次序排列成队列,从队尾进入,从队首删除。但是该算法会淘汰经常访问的页面,不适应进程实际运行的规律。
LRU算法置换最近一段时间以来最长时间未访问过的页面。根据程序局部性原理,刚被访问的页面,可能马上又要被访问;而较长时间内没有被访问的页面,可能最近不会被访问。普偏地适用于各种类型的程序,但是系统要时时刻刻对各页的访问历史情况加以记录和更新,开销太大,因此LRU算法必须要有硬件的支持。
OPT算法置换以后不再被访问,或者在将来最迟才回被访问的页面,缺页中断率最低。但是该算法需要依据以后各业的使用情况。所以OPT算法不可能实现。
实验八 页面置换模拟程序设计相关推荐
- 页面置换模拟程序设计
页面置换模拟程序设计 1.通过软件模拟页面置换过程,加深对请求页式存储管理实现原理的理解 2.理解和掌握OPT.FIFO和LRU三种页面置换算法,深入分析三者之间的优缺点. #include<s ...
- 操作系统实验八:页面置换模拟程序设计
一.实验目的 1.通过软件模拟页面置换过程,加深对请求页式存储管理实现原理的理解 2.理解和掌握OPT.FIFO和LRU三种页面置换算法,深入分析三者之间的优缺点. 二.实验环境 硬件环境:计算机一台 ...
- 操作系统实验:页面置换算法的模拟实现及命中率对比(学习笔记)
操作系统实验:页面置换算法的模拟实现及命中率对比(学习笔记) 题目要求 输入要求 输出要求 编程平台 实验成果 开始模拟 错误输入 退出程序 代码实现 抽象数据类型定义 指令地址流生成 指令地址流到页 ...
- 操作系统实验2—页面置换算法模拟程序设计
一.实验目的 对页面置换做进一步的理解. 了解页面置换的任务. 通过编程掌握页面置换算法及缺页率计算. 了解Belady现象和抖动现象. 二.实验内容 输入给出一组页面访问顺序(如页面走向是1.2.5 ...
- 【南邮操作系统实验】页面置换算法(FIFO、LRU、OPT)图形化界面(JavaFx)
页面置换算法图形化界面 前言 运行效果 源码 FIFO LRU OPT FXML界面 控制器 启动类 前言 其实以前操作系统实验的时候我写过了三份了:(命令行) 页面置换算法 (FIFO.LRU.OP ...
- android内存置换,课内资源 - 基于Android实现的页面置换模拟
一.使用说明 1.1 项目简介 请求分页分配方式的模拟,包括页面.页表.地址的转换和页面置换过程,并通过该模拟过程加深对请求调页系统的原理和实现过程的理解.并且学习Android环境下使用Java编写 ...
- 【南邮操作系统实验】页面置换算法 (FIFO、LRU、OPT)Java 版
页面置换算法Java版 先进先出置换算法(FIFO) 最近最久未使用置换算法(LRU) 最佳置换算法(OPT) 帮女朋友写了份 Python版的,Python版戳这里 帮女朋友舍友写了份 C++ 版的 ...
- 【南邮操作系统实验】页面置换算法(FIFO、LRU、OPT) C++ 版
页面置换算法 先进先出置换算法(FIFO) 最近最久未使用置换算法(LRU) 最佳置换算法(OPT) 写好了 Java 版和 Python 版的- Java版这里 Python版戳这里 帮女朋友舍友写 ...
- 【南邮操作系统实验】页面置换算法(FIFO、LRU、OPT) Python 版
页面置换算法 先进先出置换算法(FIFO) 最近最久未使用置换算法(LRU) 最佳置换算法(OPT) 本来已经写好一份 Java 版的了,然后又帮女朋友写了一份 Python 版,啊哈哈 Java版戳 ...
最新文章
- mysql利用CPU多核
- PyQt5教程——组件 Ⅱ(八)
- 【蓝桥杯Java_C组·从零开始卷】第八节、综合测试
- 临沂大学3加4计算机专业,临沂大学2021年电子信息(计算机技术方向) 硕士研究生调剂工作细则...
- ubuntu 开启 rewrite 模块
- 微软再向开发者重申:UWP 是 PC 的最佳平台
- wamp下更改mysql密码
- logging日志模块
- java注解_Java注解
- python数据分析numpy_Python数据分析之numpy学习(一)
- 机器学习 结构化数据_聊天机器人:根据结构化数据创建自然语言
- 打印机质量测试软件,打印质量测试
- C++Windows连点器制作
- 飞信2009_从飞信倒下的八个原因看运营商的复兴之路
- 什么是表压?什么是绝压?表压和绝压什么关系?
- 为小米4与小米3 Mi3 Mi4编译Cyanogenmod 12.1与13.0 (CM12与CM13) 的步骤以及错误解决
- 导数卷积 牛客 NTT
- tftp64能Ping通,但是无法load下载bin文件
- 【ubuntu拷贝目录】cp: omitting directory”错误的解释和解决办法
- “耳根”发布新作《一念永恒》,交易记录