设计一个虚拟存储区和内存工作区,并使用下述常用页面置换算法计算访问命中率。
(1)先进先出算法(FIFO)
(2)最近最少使用算法(LRU)
(3)最优置换算法(OPT)
实验要求:
(1)通过随机数产生一个指令序列,共320条指令。
(2)将指令序列转换成页面序列。
①页面大小为1KB;
②用户内存容量为4~32页;
③用户虚存容量为32KB。
④在用户虚存中,按每页存放10条指令排列虚存地址,即320条指令存在32个页面中。
(3)计算并输出不同置换算法在不同内存容量下的命中率。
命中率计算公式为:
命中率 = 1 – 页面访问失败次数 / 页面总数
#include<iostream>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<random>
#include<algorithm>
const int PAGE_SIZE = 1024;
const int INSTRUCTION_COUNT = 320;
const int PAGE_NUM = 32;
double FIFO(std::vector<int>sequence, int page_num) {
int falut_num = 0;//缺页的次数
std::queue<int>page_queue;
int free_num = page_num;
//页面指令 sequence[i]表示第i条页面指令是要去的页面的编号
std::set<int>p;
for (int i = 0; i < INSTRUCTION_COUNT; i++) {
int x = sequence[i];//要去编号为x的页面
if (p.count(x))//该页面已经存在
continue;
else {
//该页面不存在且还有剩余空间
if (free_num > 0) {
page_queue.push(x);
p.insert(x);
free_num--;
}
else {
falut_num++;
int a = page_queue.front();
p.erase(a);
page_queue.pop();
page_queue.push(x);
p.insert(x);
}
}
}
return double(1 - falut_num * 1.0 / INSTRUCTION_COUNT);
}
double LRU(std::vector<int>sequence, int page_num) {
//符合能插头且删尾的数据结构,那必然是...deque?no no no,那必然是vector
std::vector<int>p;
std::set<int>pp;
int flaut_num = 0;
int free_num = page_num;
for (int i = 0; i < INSTRUCTION_COUNT; i++) {
int x = sequence[i];
if (pp.count(x)) {
auto a = find(p.begin(), p.end(), x);//找到这个元素的位置
int aa = *a;
p.erase(a);//删除原来的位置
p.insert(p.begin(), aa);//插到头部位置
}
else {
if (free_num > 0) {//有空余空间
free_num--;
p.insert(p.begin(), x);
pp.insert(x);
}
else {
int a = p.back();
pp.erase(a);
pp.insert(x);
p.pop_back();
p.insert(p.begin(), x);
flaut_num++;
}
}
}
return double(1 - flaut_num * 1.0 / INSTRUCTION_COUNT);
}
double OPT(std::vector<int>sequence, int page_num) {
std::set<int>p;
int free_num = page_num;
int falut_num = 0;
for (int i = 0; i < INSTRUCTION_COUNT; i++) {
int x = sequence[i];
if (p.count(x))
continue;
else {
if (free_num > 0) {
free_num--;
p.insert(x);
}
else {
falut_num++;
std::map<int, int>pp;
for (int e = i + 1; e < INSTRUCTION_COUNT; e++) {
int a = sequence[e];
if (p.count(a)&&!pp.count(a)) {
pp[a] = e;
if (pp.size() == p.size())
break;
}
}
int a = 0;
if (pp.size() == p.size()) {
int b = 0;
for (auto e : pp) {
if (e.second > b) {
b = e.second;
a = e.first;
}
}
}
else {
for (auto e : pp) {
if (!p.count(e.first)) {
a = e.first;
break;
}
}
}
p.erase(a);
p.insert(x);
}
}
}
return double(1 - falut_num * 1.0 / INSTRUCTION_COUNT);
}
void see_sequence(std::vector<int>seqence) {
for (auto i : seqence)
std::cout << i << " ";
std::cout << std::endl;
}
void init(std::vector<int>& sequence,int* seqence2) {
for (int i = 0; i < INSTRUCTION_COUNT; i++) {
sequence[i] = rand() % INSTRUCTION_COUNT / 10;
seqence2[i] = sequence[i];
}
}
inline void menu() {
printf("*******************************************\n");
printf("* 原神怎么你了 原神怎么你了 原神怎么你了 *\n");
printf("* 1.查看页面序列内容 *\n");
printf("* 2.页面置换算法,启动 *\n");
printf("* 3.重新生成页面序列 *\n");
printf("* 4.exit *\n");
printf("*******************************************\n");
printf("请从1-4中选择按键:\n");
}
int main()
{
int page[PAGE_NUM]; int sequence2[INSTRUCTION_COUNT];
std::vector<int>sequence(INSTRUCTION_COUNT);//用户虚存
srand(time(NULL));//设置随机数
init(sequence,sequence2);
while (true) {
menu();
int op;
std::cin >> op;
if (op == 3)
init(sequence,sequence2);
else if (op == 1)
see_sequence(sequence);
else if (op == 2) {
std::cout << "内存大小 FIFO LRU OPT" << std::endl;
for (int i = 4; i <= 32; i++) {
double a = FIFO(sequence, i);
double b = LRU(sequence, i);
double c = OPT(sequence, i);
printf("%d\t\t%f\t\t%f\t\t%f\n", i, a, b, c);
//std::cout << a << " " << aa << std::endl;
}
}
else if (op == 4)
break;
}
return 0;
}