5种页面置换算法的实现

来源:互联网 发布:js源码解析 编辑:程序博客网 时间:2024/06/05 18:26

前几天做了一个有关页面替换算法的题,要求如下:

1 简介
要求实现多种页面替换算法,然后利用随机产生的引用串测试其性能。
2 页面替换算法
   我们做如下假设:
• 虚拟内存页面总数为P,标号从0到P1;
• 引用串RS(reference string)是一个整数序列,整数的取值范围为0到P1。RS中的每个元素p表示对页面p的一次引用;
• 物理内存由F帧组成,标号从0到F1。我们引入一个数组M[F], 数组元素M[f]中包含数字p,它表示帧f中包含页面p。页面替换算法顺次读取RS中的每个元素。对于RS中的元素值p,算法搜索数组M[F],判断是否存在某个f,使得M[f] == p。如果未发现,则表示页面缺失。这时,算法必须根据其特定的替换规则,选择一帧M[i],用页面p替换其中的内容,即令M[i] = p。
   下面讨论各种替换算法所需要的不同数据结构:
• 最佳替换算法和随机替换算法不需要其它的数据结构。 对于最佳替换 算法,通过搜索RS即足以确定应被替换的页面;对于随机替换算法,产生一个取值范围在0和F1之间的随机数,该随机数即可表示应被替换的页面。
• FIFO需要一个指向最老页面的指针(数组索引)。每当该页面被替换的时候,把该指针加1(模F)即可。
• LRU算法则需要一个尺寸为F的数组,该数组用来实现排队功能:每次处理一个新的页面引用时,则把该页放置在队列的末尾。这样, 每当需要淘汰一个页面时,从队首取到的即最长时间未被用到的页面。
• Clock算法(也叫secondchance算法)和FIFO算法一样,需要一个指针。此外,它还需要一个数组,用来记录每一帧的使用情况。

   本实验要求实现多种页面替换算法,然后利用随机产生的引用串测试其性能。

3引用串的生成
   实现了页面替换算法以后,我们还需要生成引用串,用以测试页面替换算法的性能。生成引用串的关键在于如何模拟程序的局部性。
生成不带局部性的引用串最为容易, 遗憾的是, 这和绝大多数的程序特性不符。多数程序都显示出高度的局部性,也就是说,在一个时间内,一组页面被反复引用。

   这组被反复引用的页面随着时间的推移,其成员也会发生变化。有时这种变化是剧烈的,有时这种变化则是渐进的。我们把这组页面的集合称 为当前工作集。

   我们可以为程序的这种行为方式建立如下模型。首先,我们定当前工作集由虚拟内存中连续的页面组成。这当然与实际情况不符,因为程序的代码、数据和堆栈通常分处在不同的虚拟内存区域。但是,对于研究页面替换算法来说,我们关心的只是当前工作集的大小,以及其成员更替的频繁程度。因此,从这个意义上说,我们的假设是合理的。
   我们进一步假设引用在当前工作集内的分布是均匀的。工作集可用其起始页面,以及其中包含的页面数表示。 随着时间的推移,工作集在虚拟内存中不断移动。有时,这种移动是渐进的,而有时则是剧烈的。为了给渐进移动建立模型,我们做如下假设:

工作集在固定的方向向匀速前进(例如,在处理了m个引用后,把工作集的起始页面加1)。对于剧烈移动,我们则重新随机选择工作集的起始页面 即可。剧烈移动在整个移动中的比率,我们用t表示。根据以上假设,引用串可用如下算法产生:
1. 确定虚拟内存的尺寸P,工作集的起始位置p,工作集中包含的页数e,工作集移动率m,以及一个范围在0和1之间的值t;
2. 生成m个取值范围在p和p+e间的随机数,并记录到引用串中;
3. 生成一个随机数r,0 r 1;
4. 如果r<t,则为p生成一个新值,否则p = (p+1) mod P;
5. 如果想继续加大引用串的长度,请返回第而2步,否则结束。
4 性能评测
测试不同的引用串以及不同的虚拟内存尺寸


我把页面置换算法封装起来了,引用串的生成函数放在了main函数的上面,先贴封装的算法类:

头文件如下:

#ifndef __ALG__#define __ALG__#include <vector>#include <iostream>#include <time.h>using namespace std;enum Strategy{OPT = 0,//最佳置换算法RPA,//随机置换算法FIFO,//先进先出算法LUR,//最近最久未使用算法CLOCK//时钟算法};class NodeForLUR{public:NodeForLUR() {}~NodeForLUR() {}int index;NodeForLUR* next;};class LinkForLUR{public:LinkForLUR() {}~LinkForLUR() {}NodeForLUR* head;NodeForLUR* tail;};class Algorithms{public:explicit Algorithms(int memory_size);~Algorithms();void setReferenceString(std::vector<int> rs);int exePageReplace(Strategy strategy);private:void resetMemory();int OPT(int current_serial);int RPA();int FIFO();int LUR();void updateLinkForLUR(int index);void deleteLinkForLUR(NodeForLUR* node);int CLOCK();//int page_size;int memory_size;int memory_used;int oldest_index;LinkForLUR link_for_LUR;int *memory;//模拟物理内存bool *clock;int placement_count;//置换次数std::vector<int> reference_string;};#endif // !__ALG__
CPP文件如下:


#include "stdafx.h"Algorithms::Algorithms(int memory_size){this->memory_size = memory_size;this->memory_used = 0;this->memory = new int[memory_size];this->clock = new bool[memory_size];this->link_for_LUR.head = nullptr;this->link_for_LUR.tail = nullptr;this->oldest_index = 0;this->placement_count = 0;}void Algorithms::setReferenceString(std::vector<int> rs){this->reference_string.clear();this->reference_string = rs;}int Algorithms::exePageReplace(Strategy strategy){//检测引用串的设置情况if (reference_string.empty()) {std::cout << "ERROR:引用串未设置!" << endl;return -1;}//检测是否初始化内存使用if (0 != memory_used) {resetMemory();}vector<int>::iterator ir = reference_string.begin();for (; ir < reference_string.end(); ++ir) {//是否物理内存中已存在该页面int index;for (index = 0; index < memory_used; index++) {if (memory[index] == *ir) {break;}}if (index != memory_used) {//内存存在//std::cout << "引用串第" << ir - reference_string.begin() << "位已存在物理内存中!" << endl;if (strategy == Strategy::LUR) {//策略为LUR时,更新最近最久未使用队列updateLinkForLUR(index);}else if (strategy == Strategy::CLOCK) {clock[index] = true;oldest_index = (index + 1) % memory_size;}continue;}//是否有空闲内存if (memory_used < memory_size) {memory[memory_used++] = *ir;//std::cout << "引用串第" << ir - reference_string.begin() << "位已加入空闲物理内存中!" << endl;if (strategy == Strategy::LUR) {//策略为LUR时,增加最近最久未使用队列节点if (memory_used == 1) {link_for_LUR.head = new NodeForLUR();link_for_LUR.head->index = 0;link_for_LUR.tail = link_for_LUR.head;}else {auto temp_node = new NodeForLUR();temp_node->index = memory_used - 1;temp_node->next = link_for_LUR.head;link_for_LUR.head = temp_node;}}else if (strategy == Strategy::CLOCK) {clock[memory_used - 1] = true;}continue;}//无空闲内存,页面替换int page;placement_count++;switch (strategy){case Strategy::OPT:{int current_serial = ir - reference_string.begin();page = OPT(current_serial);break;}case Strategy::RPA:page = RPA();break;case Strategy::FIFO:page = FIFO();oldest_index = (oldest_index+1)%memory_size;break;case Strategy::LUR:page = LUR();updateLinkForLUR(page);break;case Strategy::CLOCK:page = CLOCK();clock[page] = true;break;default:_ASSERTE(0);}//cout << strategy <<"  page :" << page << endl;memory[page] = *ir;}return placement_count;}/*重置内存使用*/void Algorithms::resetMemory(){std::cout << "内存使用未重置,正在重置!" << endl;while (--memory_used >= 0){memory[memory_used] = 0;}if (link_for_LUR.head != nullptr) {deleteLinkForLUR(link_for_LUR.head);link_for_LUR.head = nullptr;link_for_LUR.tail = nullptr;}memory_used++;oldest_index = 0;placement_count = 0;}/*最佳页面替换算法,返回替换页面在物理内存中的序号,下同*/int Algorithms::OPT(int current_serial){//分析是否有某个页面后续永不使用int memory_index = 0, MAX_PAGE = -1, MAX_COUNT = -1;for (; memory_index < memory_size; memory_index++){int rs_index;for (rs_index = current_serial; rs_index < reference_string.size(); ++rs_index) {if (memory[memory_index] == reference_string[rs_index]) {if (MAX_COUNT < rs_index) {//当前页面在未来将会被再次引用,记录引用位置和页面号MAX_PAGE = memory_index;MAX_COUNT = rs_index;}break;}}if (rs_index == reference_string.size()) {//找到可替换页面(存在某页面永不使用)return memory_index;}}//无页面永不使用,则返回最长时间不使用页面在物理内存中的序号return MAX_PAGE;}/*随机置换页面算法*/int Algorithms::RPA(){return rand()%memory_size;}/*先进先出算法*/int Algorithms::FIFO(){return oldest_index;}int Algorithms::LUR(){return link_for_LUR.tail->index;}void Algorithms::updateLinkForLUR(int index){//移动节点auto temp_node = link_for_LUR.head;NodeForLUR* last_node = nullptr;while (temp_node->index != index){//查找节点_ASSERT(temp_node != nullptr);last_node = temp_node;temp_node = temp_node->next;}if (temp_node == link_for_LUR.head) {//如果查找到的节点是头结点,则无改动退出。return;}if (temp_node == link_for_LUR.tail && last_node != nullptr) {//是否是尾节点且链长大于1link_for_LUR.tail = last_node;}last_node->next = temp_node->next;temp_node->next = link_for_LUR.head;link_for_LUR.head = temp_node;}/*用于删除LUR的链表*/void Algorithms::deleteLinkForLUR(NodeForLUR* node){if (node->next != nullptr) {deleteLinkForLUR(node->next);delete node;node = nullptr;}else {delete node;node = nullptr;}}/* 这里借用了FIFO算法的oldest_index游标。反正一个策略执行完也会重置。*/int Algorithms::CLOCK(){//查看是否有访问位为0的for (int index = oldest_index; index < memory_size; index++){if (!clock[index]) {oldest_index = (index + 1) % memory_size;return index;}else{clock[index] = false;}}oldest_index = 0;return CLOCK();}Algorithms::~Algorithms(){delete[] memory;delete[] clock;memory = nullptr;if (link_for_LUR.head != nullptr) {deleteLinkForLUR(link_for_LUR.head);}}

main函数所在文件如下:

#include "stdafx.h"#define _SCALE_ 100/*函数功能:用于生成引用串参数从左至右依次为:v:用于填充的引用串page_size:页面总数Pset_num:工作集中包含的页数emove:工作集移动率mjitter_rate:抖动率rs_size:预期生成的引用串长度*/void genReferenceString(vector<int>& v, int page_size, int set_num, int start_position, int move, float jitter_rate, int rs_size) {int length = 0;srand((int)time(0));while (length < rs_size){for (int count = 0; count < move; count++) {v.push_back((start_position + rand() % set_num)% page_size);length++;}int r = rand() % _SCALE_;if (r < jitter_rate*_SCALE_) {cout << "发生抖动,抖动位置为  " << length << endl;start_position = rand() % page_size;}else{start_position = (start_position + 1) % page_size;}}}int main(){Algorithms test(10);vector<int> rs;genReferenceString(rs, 100, 10, 0, 10, 0.3, 40);cout << "此次随机生成的引用串如下所示!" << endl;for (int index = 0; index < 40; index++) {cout << "\t" << rs[index] ;if (index % 5 == 4) {cout << endl;}}Strategy strategy[] = { Strategy::OPT, Strategy ::RPA, Strategy::FIFO, Strategy::LUR, Strategy::CLOCK};test.setReferenceString(rs);for (int index = 0; index < 5; ++index) {cout << "第" << index << "号策略:" << endl;cout << "共计交换页面" << test.exePageReplace(strategy[index]) << "次!" << endl;}    return 0;}

stdafx.h文件里我放了这么一句,所以要包含一下:
#include "Algorithms.h"


程序的注释也很详细,我就不做过多解释了。有问题可以私信问我。

0 0
原创粉丝点击