详细知识点可以参考请求分页虛拟存储管理及页面置换算法
请求分页储存管理
请求分页系统是建立在基本分页系统的基础上,增加了请求调页功能和页面置换功能形成的页式虚拟储存管理。(必须要需要的硬件和软件支持。)
页置换算法
常用的页置换算法有:
- 最佳置换算法(OPT)
- 先进先出算法(FIFO)
- 最近最久未使用置换算法(LRU)
效果
代码模拟
主要包含生成随机访问序列和打印表示访问状态的表格,所以比较繁杂。可以下载打包好的模拟程序。
// LRU算法模拟
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
using namespace std;
typedef struct {
int visit;
vector<int> block;
bool loss;
bool replace;
}TableItem;
void printTable(vector<TableItem> history, unsigned int blockCount);
void FIFO(int blockCount, vector<int> & visit);
void OPT(int blockCount, vector<int> & visit);
void LRU(int blockCount, vector<int> & visit);
void scan(int & blockCount, vector<int> & visit) {
cout << "1.随机生成访问序列" << endl;
cout << "2.手动输入序列" << endl;
int op;
while (true)
{
cout << "请选择:" << endl;
cin >> op;
if (op == 1 || op == 2)break;
}
if (op == 1) {
int n, num;
cout << "请输入内存物理块数:" << endl;
cin >> blockCount;
cout << "请输入虚页的个数:" << endl;//0 -- n-1
cin >> n;
cout << "请输入虚页访问次数:" << endl;
cin >> num;
//生成随机访问序列
visit.clear();
cout << "生成的随机序列为:" << endl;
for (int i = 0; i < num; i++) {
int ran = (int)(n - 1)*rand() / (RAND_MAX + 1);
visit.push_back(ran);
cout << ran << " ";
}
cout << endl;
}
else if (op == 2) {
cout << "请输入内存物理块数:" << endl;
cin >> blockCount;
cout << "请输页面访问序列:(最后一个数据回车后 输入 Ctrl Z 回车结束输入)" << endl;
visit.clear();
while (!cin.eof()) {
int v;
cin >> v;
if (cin.fail()) break;
visit.push_back(v);
}
}
}
int main()
{
srand((int)time(0)); // 产生随机种子
//4 3 2 1 4 3 5 4 3 2 1 5
int blockCount = 3;
vector<int> visit = { 4,3,2,1,4,3,5,4,3,2,1,5 };
int op;
while (true)
{
cin.clear();
cin.sync();
cout << "请选择算法:" << endl;
cout << "1.FIFO" << endl;
cout << "2.OPT" << endl;
cout << "3.LRU" << endl;
cout << "4.退出" << endl;
cin >> op;
switch (op) {
case 1:
scan(blockCount, visit);
cout << "FIFO" << endl;
FIFO(blockCount, visit);
break;
case 2:
scan(blockCount, visit);
cout << "OPT" << endl;
OPT(blockCount, visit);
break;
case 3:
scan(blockCount, visit);
cout << "LRU" << endl;
LRU(blockCount, visit);
break;
case 4:
exit(0);
}
}
system("pause");
}
//j就是在FIFO基础上 在访问过存在的序列时调整一下序列的位置
void LRU(int blockCount, vector<int> & visit) {
vector<TableItem> history;
int loss = 0;
vector<int> block;
for (int & i : visit) {
TableItem item;
item.visit = i;
item.loss = false;
item.replace = false;
//块内不包含
vector<int>::iterator it = find(block.begin(), block.end(), i);
if (it == block.end()) {
//如果块满了删除第一个进入的
if (block.size() == blockCount) {
block.pop_back();
item.replace = true;
}
loss++;
block.insert(block.begin(), i);
item.loss = true;
}
else {
//如果有 则把他放第一个
block.erase(it);
block.insert(block.begin(), i);
}
item.block = block;
history.push_back(item);
}
printTable(history, blockCount);
cout << "缺页次数:" << loss << ' ' << "缺页率:" << float(loss) / visit.size() * 100 << '%' << endl;;
}
//OPT
//根据后blockCount个序列预测 不足blockCount按剩余的序列预测
//如果序列最后几位都预测不到 默认置换块首的那一个 这里可能有待细化
void OPT(int blockCount, vector<int> & visit) {
vector<TableItem> history;
int loss = 0;
vector<int> block;
for (unsigned int i = 0; i < visit.size(); i++) {
TableItem item;
item.visit = visit[i];
item.loss = false;
item.replace = false;
//块内不包含
if (find(block.begin(), block.end(), visit[i]) == block.end()) {
//如果块满了 根据后blockCount步预测
if (block.size() == blockCount) {
bool rep = false;
auto step = blockCount;
if (i + 1 + blockCount > visit.size())step = visit.size() - i - 1;
for (unsigned int k = 0; k < block.size(); k++) {
unsigned int j = i + 1;
for (; j < i + 1 + step; j++) {
if (block[k] == visit[j]) {
break;
}
}
if (j == i + 1 + step) {
rep = true;
block[k] = visit[i];
item.replace = true;
break;
}
}
//如果预测的都命中 选最后一个置换
if (rep == false) {
item.replace = true;
block.pop_back();
block.push_back(visit[i]);
}
}
else {
block.push_back(visit[i]);
}
loss++;
item.loss = true;
}
item.block = block;
history.push_back(item);
}
printTable(history, blockCount);
cout << "缺页次数:" << loss << ' ' << "缺页率:" << float(loss) / visit.size() * 100 << '%' << endl;
}
//FIFO
void FIFO(int blockCount, vector<int> & visit) {
vector<TableItem> history;
int loss = 0;
vector<int> block;
for (int & i : visit) {
TableItem item;
item.visit = i;
item.loss = false;
item.replace = false;
//块内不包含
if (find(block.begin(), block.end(), i) == block.end()) {
//如果块满了删除第一个进入的
if (block.size() == blockCount) {
block.pop_back();
item.replace = true;
}
loss++;
block.insert(block.begin(), i);
item.loss = true;
}
item.block = block;
history.push_back(item);
}
printTable(history, blockCount);
cout << "缺页次数:" << loss << ' ' << "缺页率:" << float(loss) / visit.size() * 100 << '%' << endl;
}
void printTable(vector<TableItem> history, unsigned int blockCount) {
cout.setf(std::ios::left);
cout.width(12);
cout << "页访问顺序" << '\t';
for (TableItem item : history) {
cout << item.visit << " ";
}
cout << endl;
cout.width(10);
cout << "内存块数=";
cout.width(2);
cout << blockCount << '\t';
for (unsigned int i = 0; i < blockCount; i++) {
if (i != 0) {
cout.width(12);
cout << " " << '\t';
}
for (TableItem item : history) {
cout.width(2);
if (item.block.size() > i) {
cout << item.block[i];
}
else {
cout << ' ';
}
cout << " ";
}
cout << endl;
}
cout.width(12);
cout << "缺页" << '\t';
for (TableItem item : history) {
cout.width(2);
cout << (item.loss ? "√" : " ");
cout << " ";
}
cout << endl;
cout.width(12);
cout << "置换" << '\t';
for (TableItem item : history) {
cout.width(2);
cout << (item.replace ? "√" : " ");
cout << " ";
}
cout << endl;
}