东南大学 操作系统实验3 页替换算法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
表
。
Head
3/9
源程序及注释
LRU.h 负责数据结构的存储
#pragma once #include <iostream> using namespace std;
struct LRU_w_counter {
//计数器实现的LRU int counter; int ID;
LRU_w_counter() {
实验内容
操作系统实验报告
09010422 何博伟
2013 年 5 月 22 日
编写程序实现 LRU 算法及其近似算法,并分析各算法的时间复杂度、空间复杂度和实现难 度;通过随机生成页面访问序列,测试所实现算法的的页错误率,并加以比较和分析。
实验目的
通过实验,理解 LRU 页面置换算法的算法思想及其实现方法,比较各种实现算法的复杂度 和实现难度,体会 LRU 算法与各种近似算法间的区别,并进而加深对虚拟内存概念的理解。
Second Chance 算法
根据算法原理,首先设定一个单链表项的结构 LRU_AA_Frame,里面存储 1 位的访问位
(用 bool 类型),以及后继节点的指针。
第二,构造了一个容器 LRU_AA_Container 以存储这些帧。容器采用循环的单链表结构,
设定一个头指针,一个最近访问项目指针,列表尾部的后继节点指向表头即可实现循环单链
//没有命中,如果能新增,那新增一个 if(size < capacity) {
pItem = Insert(pageID); pItem->ref_bit = true; pLastAccess = pItem; return true; } //无法新增,只能替换... pItem = pLastAccess; while(true) { if(pItem->ref_bit == false) {
LRU_AA_Container(int _capacity) {
capacity = _capacity; size = 0; pHead = NULL; pLastAccess = NULL; }
LRU_AA_Frame* Insert(int pageID) {
if (size >= capacity) {
//victim! Replace(pItem,pageID); pLastAccess = pItem; return true; } else { pItem->ref_bit = false; //ref-
bit置0 个..
} pItem = pItem->pNext;//继续看下一
} } };
Additional-Ref.-Bits 算法
数据结构与 LRU 的计数器实现类似,将 Item 中的计数器值换成 unsigned char 类型即可实现 8 位的 Reference Bits,增加右移(>>=1)、置位(|=0x80)函数。 运行时采用类似计数器实现 LRU 算法的函数结构即可,比较大小的时候 unsigned char 自己 就能比较大小,无需另外写函数。
ID = -1 ; //空槽 counter = 65536; } };
struct LRU_ARB {
//Additional-Ref.-Bits实现的LRU unsigned char refBits; int ID;
LRU_ARB() {
ID = -1 ; //空槽 refBits = 0x0; }
设计思路及流程图
主函数根据实验材料提供的思路,用如下形式运行: while(已测页面数<要求测试页面数) { 1)随机产生新的访问页号 2)调用算法决定是否需要置换页面,如需要,调整内存相关状态,更新页错误数 }
其中随机访问的页号由 srand 函数根据时间等生成随机种子,然后产生伪随机数。
程序流程图如下:
};
struct LRU_s_Container {
//一个容器... LRU_s_Item *pFront;
//栈顶指针
4/9
LRU_s_ItemBaidu Nhomakorabea*pEnd ; int capacity; int size;
//栈底指针 //容量
LRU_s_Container(int _capacity) {
capacity = _capacity; size = 0; pFront = NULL; pEnd = NULL; }
cerr << "ERROR! Container oversize!" << endl;
return NULL; } LRU_AA_Frame *pItem = pHead; LRU_AA_Frame *newFrame = new LRU_AA_Frame;
5/9
newFrame->ID = pageID; if (pItem == NULL) {
if (pFront != NULL) pFront->head = newHeadItem;
if (pEnd == NULL) pEnd = newHeadItem; //End...
pFront = newHeadItem; size ++; return pFront; }
LRU_s_Item* Replace(int pageID) {
pItem->tail;
if(pItem->tail != NULL) //防止 栈底情况
pItem->tail->head = pItem->head;
else {
//改动了栈底,要修改栈底 指针了!
pEnd = pItem->head; } pFront->head = pItem; pItem->head = NULL; pItem->tail = pFront; pFront = pItem; return false; } pItem = pItem->tail; //一路找.. } /////看来是找不到了.. if(size < capacity) { //还没有满,只要push就行 Push(pageID); return true; } Replace(pageID); //还是得替换 return true; } };
//空容器 newFrame->pNext = newFrame; pHead = newFrame; size ++; return newFrame; } while(pItem->pNext != pHead) pItem = pItem->pNext; //找到末尾 newFrame->pNext = pHead; pItem->pNext = newFrame; size ++; return newFrame; }
struct LRU_AA_Frame {
bool ref_bit; int ID; LRU_AA_Frame *pNext; LRU_AA_Frame () {
ref_bit = false; ID = -1; } };
struct LRU_AA_Container {
//Second-chance Page-rep. Algorithm LRU_AA_Frame *pHead; LRU_AA_Frame *pLastAccess; int capacity; int size;
1/9
程序入口
用户输入最大 内存帧数
初始化各变量及容器
N
已测页面数<
要求测试页面数?
Y 随机产生访问页号
调用各算法决定是否 要替换页面
统计替换结果,写入 log
程序结束
主要数据结构及其说明
LRU 的计数器实现
使用自定义结构 LRU_w_counter 实现每一个帧项目的数据结构,里面存储页面 ID 号以及计 数器值。运行时,遍历一个这个结构的数组 lru_w_counter_list 实现替换算法。
源.cpp 主程序
#include "LRU.h" #include <iostream> #include <ctime> //time #include <stdlib.h> //srand,rand #include <fstream> using namespace std;
typedef enum {
LRU_s_Item* Push(int pageID) {
if(size >= capacity) {
//Need replace... return NULL; } LRU_s_Item *newHeadItem = new LRU_s_Item; newHeadItem->ID = pageID; newHeadItem->tail = pFront;
LRU_C, LRU_S, ARB, SC }; int MAX_MEM_FRAME; //最大内存帧数 const int MAX_PAGE_NUM = 10; //最大页数量 const int TEST_PAGE_NUM = 3000; //测试页面数
int page_falut_time[4] = {0}; //页错误数量 LRU_w_counter *lru_w_counter_list; LRU_s_Container *lru_s_container; LRU_ARB *lru_arb_list; LRU_AA_Container *lru_aa_container;
2/9
LRU 的栈实现
栈顶指针 Item
… Item Item
… Item
栈底指针
使用自定义结构 LRU_s_Item 来实现每一个帧项目的数据结构,里面存储页面 ID 号,头 指针、尾指针以实现双向链表的结构。
容器使用自定义结构 LRU_s_Container 来实现一个栈,作为帧的容器。结构中有栈顶、 栈底指针,容量以及实际使用量。使用函数 Push 来向栈顶增加一个元素(如果空间没有填满), 函数 Replace 来将栈底的元素(最少访问的元素)替换为某个新元素,函数 TryAccess 实现尝 试页面的访问,如果出现页错误那替换或是增加相关的页,当出现页错误时返回 true 用于 统计,没有页错误则返回 false。
//抽出栈底,然后push新的进去..完事儿 LRU_s_Item *oldEnd = pEnd; pEnd = pEnd->head; if (pEnd != NULL)
pEnd->tail = NULL; size --;
return Push(pageID); }
bool TryAccess(int pageID) //返回值 : 有page-fault 则返回true
void MoveRight() {
refBits >>= 1; }
void Access() {
refBits |= 0x80; } };
struct LRU_s_Item {
int ID; LRU_s_Item *head; LRU_s_Item *tail;
LRU_s_Item() {
ID = -1; head = NULL; tail = NULL; }
void Replace(LRU_AA_Frame *pFrame, int pID) {
pFrame->ID = pID; pFrame->ref_bit = true; }
bool TryAccess(int pageID) //返回值:是否发生页错误,true->有页错误
{ LRU_AA_Frame *pItem = pLastAccess; if(pItem == NULL) { pItem = Insert(pageID); pItem->ref_bit = true; pHead = pItem; pLastAccess = pItem; return true; } do { if(pageID == pItem->ID) { //HIT! pItem->ref_bit = true; pLastAccess = pItem; return false; } pItem = pItem->pNext; }while(pItem != pLastAccess);
{ LRU_s_Item * pItem = pFront; while(pItem != NULL) { if(pageID == pItem->ID) { //HIT! //需要将这个指针上浮到顶上... if(pItem == pFront) return false; //它就在栈
顶,不用移动了... pItem->head->tail =