页面置换算法的实现

1.最佳置换算法

实现思路
  • 首先创建一个进程结构体,属性为该进程需要的页面序列和分配给该进程的物理块数量(个人认为,单进程就能实现,所以这个结构体不使用也可以)
  • 在主函数中进行初始化,初始化结构体进程,之后用户输入序列和物理块数量,赋值给结构体的属性
  • 置换算法函数,开始先将内存物理块填满,此时不算作页面置换,按顺序将几个页面加入内存物理块即可,之后开始判断序列中每一个页面是否在内存中,在的话则跳过,不在的话触发页面中断,此时需要判断将内存中的那个页面置换出去,我采用的方法是求出:此时(内存中的几个页面下一次出现的索引)与(当前内存所需要的页面的索引)的差值,将差值最大的替换掉,循环往复
  • 还需写一下求上述差值的函数,看代码即可。
  • 对于序列中的每个页面的处理采用循环实现
代码如下:
//最佳置换算法
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;

//进程
struct PCB {
	vector<int> need_page;  //该进程需要的页面
	int physical_num;  //分配给进程的物理块数量
};

//函数声明
void show(PCB pcb, vector<int> memory, int change_sum);
int max_vector(vector<int> v);
int time_diff_sum(vector<int> need_page, int index);
void optimal(PCB& pcb, vector<int> memory);


//求vector中的最大值
int max_vector(vector<int> v) {
	int temp = 0;
	for (int i = 1; i < v.size(); i++) {
		if (v[i] > v[temp]) temp = i;
	}
	return temp;
}


//求页面出现时间差值,参数为要求的页面所在向量的索引(最佳置换算法)
//差值越大的先被替换掉
int time_diff_sum(vector<int> need_page, int index, vector<int> memory, int memory_in) {
	int sum = 1000;
	for (int i = index + 1; i < need_page.size(); i++) {
		if (need_page[i] == memory[memory_in]) {
			sum = i - index;
			break;
		}
	}
	return sum;
}

//最佳置换算法(memory代表内存物理块)
void optimal(PCB& pcb, vector<int> memory) {
	//置换次数
	int change_sum = 0;
	int sum = 0;
	//内存物理块中每个页面对应的最原始的索引,方便求差值
	//先将物理块放满
	for (int i = 0; i < pcb.physical_num; i++) {
		memory.push_back(pcb.need_page[i]);
		show(pcb, memory, change_sum);
	}
	
	//放入接下来的页面,先判断目前的内存中是否已有,再进行置换
	vector<int> time_diff;  //存储当前每个物理块中页面的出现时间差值

	for (int i = pcb.physical_num; i < pcb.need_page.size(); i++) {


		cout << "此时进行页号为 " << pcb.need_page[i] << "的操作------------------" << endl;
		cout << "                                        |" << endl;
		//判断目前内存中是否有已有
		int flag = 0;
		for (int k = 0; k < memory.size(); k++) {
			if (memory[k] == pcb.need_page[i]) {
				flag = 1;
			}
		}
		//flag说明物理块(内存)中已经存在该页面,则跳出本次循环
		if (flag == 1) {
			cout << "页面已在内存,没有发生置换!" << endl;
			show(pcb, memory, change_sum);
			continue;
		}

		//页面置换
		cout << "页面不在内存中,触发缺页中断" << endl;
		for (int j = 0; j < memory.size(); j++) {
			sum = time_diff_sum(pcb.need_page, i, memory, j);
			time_diff.push_back(sum);
		}
		//求差值最大的页面,差值最大的要被替换
		int max_sum = max_vector(time_diff);
		time_diff.clear();

		cout << "页面" << memory[max_sum] << "被淘汰,状态位变为0" << endl;

		memory[max_sum] = pcb.need_page[i];

		cout << "页面" << pcb.need_page[i] << "进入内存物理块中,状态位变为1" << endl;

		//展示
		change_sum++;
		show(pcb, memory, change_sum);
	}
	float persent_rate;
	persent_rate = float(change_sum+3) / float(pcb.need_page.size());
	cout << "(最佳置换算法)此序列下的缺页率为:" << persent_rate << setprecision(2) << endl;
}

//内存中页面情况展示(change_sum为当前一共置换的次数)
void show(PCB pcb, vector<int> memory, int change_sum) {
	cout << "  " << endl;
	cout << "   -------此时内存中页面情况为-------   " << endl;
	for (int i = 0; i < memory.size(); i++) {
		cout << "----";
	}
	cout << endl;

	for (int i = 0; i < memory.size(); i++) {
		cout << "| " << memory[i] << " ";
	}
	cout << "|" << endl;
	for (int i = 0; i < memory.size(); i++) {
		cout << "----";
	}
	cout << endl;
	cout << "   此时置换次数为:" << change_sum << "次" << endl;
	cout << "|                                       |" << endl;
	cout << "-----------------------------------------" << endl;
	cout << "  " << endl;
	cout << "  " << endl;
}


int main() {
	cout << "  " << endl;
	cout << "  " << endl;
	cout << "                    ***此算法为最佳置换算法***" << endl;
	cout << "  " << endl;
	cout << "  " << endl;
	cout << "---进行进程和内存(物理块)和页面号引用串初始化---" << endl;
	//创建进程
	PCB pcb;

	cout << "请输入页面号引用串(使用数字代表ID号)" << endl;
	cout << "输入时ID号之间使用空格,输入完成后使用回车" << endl;
	int cin_page_num;
	char c;
	while ((cin >> cin_page_num).get(c)) {
		pcb.need_page.push_back(cin_page_num);
		if (c == '\n')
			break;
	}
	if (pcb.need_page.size() > 0)
		cout << "页面号引用串初始化成功!" << endl;

	cout << "  " << endl;
	cout << "请输入物理块数量(一般为3)" << endl;
	int cin_physical_num = 0;
	cin >> cin_physical_num;
	pcb.physical_num = cin_physical_num;
	if (pcb.physical_num != 0)
		cout << "物理块数量初始化成功!" << endl;
	cout << "  " << endl;
	//内存初始化
	vector<int> memory;
	cout << "内存初始化成功" << endl;
	cout << "---初始化完毕---" << endl;
	cout << "  " << endl;

	//调用置换算法
	optimal(pcb, memory);

	return 0;
}

2.先进先出置换算法

实现思路
  • 创建页面结构体,属性在代码中可见,还有需要的变量以及向量数组
  • 创建页面结构体数组,并初始化,物理块初始化,内存初始化。
  • 先进先出置换算法函数,同理,先将物理块填满,吗,每添加一个页面,都需要将内存中的每个页面的stay_time停留时间+1(我使用页面停留时间来判断那个最先进入页面),接下来是其余页面,判断是否需要页面置换,需要的话则比较内存中的页面的stay_time,值最大的说明最先进入内存,则淘汰,添加新的页面,注意每个页面的stay_time的+1。
  • 输出函数中添加了每个页面的情况信息,状态位,访问位等
代码实现:
//先进先出页面置换算法
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Page {
	int stay_time;  //在内存中停留的时间
	int ID;         //页面号
	int memory_ID;  //所在的物理块号,如果不在内存中,则为-1

	int status;     //状态位
	int visited;    //访问位
};

//需要的向量数组和变量
vector<int> need_page;  //存储页面号引用串
vector<Page> memory;     //代表内存物理块
int physical_num = -1;  //物理块数量
Page page[50];          //页面结构体数组

//函数声明
void fifo(Page page[], vector<Page> memory, vector<int> need_page);
void show(vector<Page> memory, int change_sum, Page page1);


//先进先出页面置换算法
void fifo(Page page[], vector<Page> memory, vector<int> need_page) {
	int change_sum = 0;  //置换次数
	for (int i = 0; i < need_page.size(); i++) {
		//刚好直接放入内存物理块的页面
		if (memory.size() < physical_num) {
			memory.push_back(page[i]);
			memory[i].memory_ID = i;
			memory[i].status = 1;
			memory[i].visited = 1;
			for (int k = 0; k < memory.size(); k++) {
				memory[k].stay_time++;
			}
			cout << "--------------------------------------------" << endl;
			cout << "                                           |" << endl;
			cout << "                                           |" << endl;
			cout << "此时内存物理块未满,页面直接放入,无需置换!" << endl;
			show(memory, change_sum, memory[i]);
		}
		//物理块数量索引之后的页面
		else {
			//看新的页面号在不在内存中
			int flag = 0;
			for (int j = 0; j < memory.size(); j++) {
				if (memory[j].ID == page[i].ID) {
					flag = 1;
					break;
				}
			}
			//内存中已经存在
			if (flag == 1) {
				cout << "此时内存中已有该页面------------------------" << endl;
				cout << "                                           |" << endl;
				cout << "                                           |" << endl;
				page[i].stay_time = 0;
				page[i].memory_ID = -1;
				page[i].status = 0;
				page[i].visited = 1;
				for (int k = 0; k < memory.size(); k++) {
					memory[k].stay_time++;
				}
				show(memory, change_sum, page[i]);
			}
			//内存中不存在
			else {
				cout << "此时内存中没有该页面,需要进行置换----------" << endl;
				cout << "                                           |" << endl;
				cout << "                                           |" << endl;
				//求memory中停留时间最长的,并替换掉
				int stay_time_max_index = 0;
				for (int e = 0; e < memory.size(); e++) {
					if (memory[e].stay_time > memory[stay_time_max_index].stay_time) {
						stay_time_max_index = e;
					}
				}

				for (int k = 0; k < memory.size(); k++) {
					memory[k].stay_time++;
				}

				cout << "**页面" << memory[stay_time_max_index].ID << "被淘汰" << endl;
				memory[stay_time_max_index] = page[i];
				memory[stay_time_max_index].stay_time = 1;
				memory[stay_time_max_index].memory_ID = stay_time_max_index;
				memory[stay_time_max_index].status = 1;
				memory[stay_time_max_index].visited = 1;
				change_sum++;

				cout << "**页面" << page[i].ID << "进入内存物理块" << endl;
				show(memory, change_sum, memory[stay_time_max_index]);
			}
		}
	}
	float persent_rate;
	persent_rate = float(change_sum + 3) / float(need_page.size());
	cout << "(先进先出算法)此序列下的缺页率为:" << persent_rate << endl;
}

//展示此时内存情况
void show(vector<Page> memory, int change_sum, Page page1) {

	cout << " " << endl;
	cout << "此页面信息:" << endl;
	cout << " ------ -------- -------- ------ ------" << endl;
	cout << "|页面号|停留时间|物理块号|状态位|访问位|" << endl;
	cout << " ------ -------- -------- ------ ------" << endl;
	cout << "|  " << page1.ID << "   |   " << page1.stay_time << "   |    " << page1.memory_ID
		<< "   |   " << page1.status << "   |   " << page1.visited << "  |" << endl;
	cout << " ------ -------- -------- ------ ------" << endl;

	cout << "  " << endl;
	cout << "   -------此时内存中页面情况为-------   " << endl;
	for (int i = 0; i < memory.size(); i++) {
		cout << "----";
	}
	cout << endl;

	for (int i = 0; i < memory.size(); i++) {
		cout << "| " << memory[i].ID << " ";
	}
	cout << "|" << endl;
	for (int i = 0; i < memory.size(); i++) {
		cout << "----";
	}
	cout << endl;
	cout << "   此时置换次数为:" << change_sum << "次" << endl;
	cout << "                                           |" << endl;
	cout << "                                           |" << endl;
	cout << "--------------------------------------------" << endl;
	cout << "  " << endl;
	cout << "  " << endl;

}

int main() {
	//主页面布局
	cout << "  " << endl;
	cout << "  " << endl;
	cout << "                    ***此算法为先进先出算法***" << endl;
	cout << "  " << endl;
	cout << "  " << endl;
	cout << "---进行进程和内存(物理块)和页面号引用串初始化---" << endl;
	cout << " " << endl;
	cout << "请输入页面号引用串(使用数字代表ID号,个数上限为50)" << endl;
	cout << "输入时ID号之间使用空格,输入完成后使用回车" << endl;

	//--初始化开始
	//页面号引用串初始化
	int cin_page_num;
	char c;
	while ((cin >> cin_page_num).get(c)) {
		need_page.push_back(cin_page_num);
		if (c == '\n')
			break;
	}
	if (need_page.size() > 0)
		cout << " " << endl;
	cout << "页面号引用串初始化成功!" << endl;

	//页面结构体初始化
	for (int i = 0; i < need_page.size(); i++) {
		page[i].ID = need_page[i];
		page[i].stay_time = 0;
		page[i].memory_ID = -1;
		page[i].status = 0;
		page[i].visited = 0;
	}

	cout << "  " << endl;
	//物理块初始化
	cout << "请输入物理块数量(一般为3)" << endl;
	int cin_physical_num = 0;
	cin >> cin_physical_num;
	physical_num = cin_physical_num;
	if (physical_num != 0)
		cout << " " << endl;
	cout << "物理块数量初始化成功!" << endl;
	cout << "  " << endl;
	//内存初始化
	cout << "内存初始化成功" << endl;
	cout << " " << endl;
	cout << "---初始化完毕---" << endl;
	cout << "  " << endl;
	//--初始化结束

	//执行先进先出置换算法
	fifo(page, memory, need_page);

	return 0;
}