利用单向循环链表结构实现如下内存页置换策略CLOCK Algorithm:
假设缓冲池有6个缓冲页,以单向循环链表结构组织,结构如下图所示。缓冲池初始状态:所有缓冲页可用,指针P指向下一个即将被分配的缓冲页。缓冲池包含的缓冲页数作为程序运行参数设置,该参数的有效设置范围为[5, 10]。
1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
生成一组随机物理页访问序列,页编号范围是0到19,页面访问序列长度作为程序运行参数设置。如:9, 1, 10, 1, 9, 18, 7, 7, 12, 17为一个长度为10的物理页访问序列。
对每一次物理页访问,若该页已经在缓冲池中,则显示Hit并将该页对应的缓冲页状态更改为R= 1;若该页不在缓冲池中,则分配一个缓冲页并将对应缓冲页的状态设为R=0;
当需要分配一个缓冲页给当前访问的物理页时:若指针P指向的缓冲页状态为R=1,表示该页刚刚被访问过应该继续保留在缓冲池中,因此将该页的状态更改为R=0,并使P指向下一个缓冲页;若指针P指向的缓冲页状态为R=0,表明该页已经有较长时间没有被访问,可以将该缓冲页分配给当前访问的物理页。
Link.h
#pragma once
template<typename E> class Link {
public:
int r = 0;
E element;
Link *next;
Link(const E& elemval, Link* nextval = NULL)
{
element = elemval; next = nextval;
}
Link(Link* nextval = NULL) {
next = nextval;
}
};
LLink.h
#pragma once
template <typename E> class LList {
private:
Link<E>* head;
Link<E>* tail;
Link<E>* curr;
int cnt;
void init() {
curr = tail = head = new Link<E>;
int cnt = 0;
}
public:
LList() //构造函数
{
init();
}
void print() const //输出
{
Link<E>* temp = head; //遍历
cout << temp->next->element<<" ";
temp = temp->next;
while (temp->next != head->next)
{
cout << temp->next->element << " ";
temp = temp->next; //下一个结点
}
cout << endl;
}
void clear()
{
removeall();
init();
}
void insert(const E& it) {
curr->next = new Link<E>(it, curr->next);
if (tail == curr)
tail = curr->next;
cnt++;
}
void append(const E& it) {
tail = tail->next = new Link<E>(it, head->next);
cnt++;
}
E remove() {
Assert(curr->next != NULL, "No element");
E it = curr->next->element;
Link<E>* ltemp = curr->next;
if (tail == curr->next)
{
tail = curr;
}
curr->next = curr->next->next;
delete ltemp;
cnt--;
return it;
}
void moveToStart() {
curr = head;
}
void moveToEnd() {
curr = tail;
}
void prev() {
if (curr == head)
{
return;
}
Link<E>*temp = head;
while (temp->next != curr) {
temp = temp->next;
}
curr = temp;
}
void next() { //循环链表
curr = curr->next;
}
int length() const {
return cnt;
}
int currPos() const {
Link<E>* temp = head;
int i;
for (i = 0; curr != temp; i++)
{
temp = temp->next;
}
return i;
}
void moveToPos(int pos) {
Assert((pos >= 0) && (pos <= cnt), "超出范围了!");
curr = head;
for (int i = 0; i < pos; i++)
{
curr = curr->next;
}
}
const E& getValue() const {
return curr->next->element;
}
const int& getR() const {
return curr->next->r;
}
void changeE(const E& it) {
curr->next->element = it;
}
void changeR(const int it) {
curr->next->r = it;
}
};
Clock.cpp
#include<iostream>
#include<time.h>
#include"Link.h"
#include"LLink.h"
using namespace std;
#define random(x) (rand()%x)
void genSeq(int seq_len, int a[]) {
srand((int)time(0));
for (int i = 0; i < seq_len; i++)
{
a[i] = random(19);
}
}
void allocBuff(LList<int> temp, int a) {
while (temp.getR() == 1)
{
temp.changeR(0);
temp.next();
}
temp.changeE(a);
}
void visitPage(int buf_len, LList<int> temp, int a) {
for (int i = 0; i < buf_len; i++)
{
if (temp.getValue() == a)
{
cout << "Hit";
temp.changeR(1);
return;
}
temp.next();
}
allocBuff(temp,a);
}
void ClockPR(int buf_len, int seq_len, int a[]) {
LList<int> clock;
for (int i = 0; i < buf_len; i++)
{
clock.append(20); //20代表空
}
for (int i = 0; i < seq_len; i++)
{
visitPage(buf_len, clock, a[i]);
cout << "第" << i + 1 << "次访问:";
clock.print();
clock.next();
}
}
int main() {
cout << "输入页面访问序列长度:" << endl;
int seq_len;
cin >> seq_len;
int *a = new int[seq_len];
genSeq(seq_len, a);
cout << "输入范围为[5,10]的缓存页数:" << endl;
int buf_len;
cin >> buf_len;
while (buf_len < 5 || buf_len>10) {
cout << "范围为[5,10]哦!" << endl;
cin >> buf_len;
}
ClockPR(buf_len, seq_len,a);
system("pause");
}