運作結果
(1)data.txt文本檔案:
圖1 輸入檔案
将頁面引用串輸入到名為data.txt的文本檔案中,以空格隔開。
(2)各種置換算法的輸出結果:
圖2 OPT頁面置換算法運作結果
圖3 FIFO頁面置換算法運作結果
圖4 LRU頁面置換算法運作結果
圖5 Clock頁面置換算法運作結果
圖6 LRU頁面置換算法運作結果
完整代碼
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#define random(a,b) (rand()%(b-a)+a)
using namespace std;
// 總虛頁數
int t;
// 實頁數
int size;
// 序列
vector<int> v;
// 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
void print(vector<pair<int, vector<int>>> res, int lackPageNum, int totalNum){
for (int i = 0; i < size; ++i) {
// 周遊每一個序列的第i個數
for (int j = 0; j < res.size(); ++j) {
printf("|");
pair<int, vector<int>> cur = res[j];
int isLack = cur.first;
vector<int> v = cur.second;
if(!isLack || v.size() < (i + 1)){
printf(" ");
}else{
printf("%3d", v[i]);
}
printf(" ");
}
puts("|");
}
printf("缺頁數為:%d\n", lackPageNum);
printf("命中數:%d\n", (totalNum - lackPageNum));
printf("缺頁率為:%.3f%%\n", (lackPageNum * 100.0 / totalNum));
printf("命中率為:%.3f%%\n", ((totalNum - lackPageNum) * 100.0 / totalNum));
}
void FIFO(){
// 結果<是否缺頁,頁面>
vector<pair<int, vector<int>>> res;
// 上一頁
vector<int> pre;
// 判斷是否缺頁的
bool flag;
int lackPageNum = 0;
for(int num: v){
flag = true; // 是否缺頁
for (int i = 0; i < pre.size(); ++i) {
if(num == pre[i]){
flag = false;
}
}
if(!flag){
res.push_back(make_pair(0, vector<int>(pre.begin(), pre.end())));
continue;
}
lackPageNum++;
if(pre.size() < size){
pre.push_back(num);
}else{
// 缺頁則換出隊頭
pre.erase(pre.begin());
pre.push_back(num);
}
res.push_back(make_pair(1, vector<int>(pre.begin(), pre.end())));
}
printf("FIFO(先進先出)算法:\n");
print(res, lackPageNum, t);
puts("");
puts("");
}
void LRU(){
// <是否缺頁,頁面>
vector<pair<int, vector<int>>> res;
// 上一頁
vector<int> pre;
// 判斷是否缺頁的
bool flag;
// 缺頁數
int lackPageNum = 0;
// 目前頁在隊中那個位置
int idx = 0;
for(int num: v){
flag = true; // 是否缺頁
for (int i = 0; i < pre.size(); ++i) {
if(num == pre[i]){
flag = false;
idx = i;
}
}
if(!flag){
// 換到隊頭
pre.erase(pre.begin() + idx);
pre.insert(pre.begin(), num);
res.push_back(make_pair(0, vector<int>(pre.begin(), pre.end())));
continue;
}
lackPageNum++;
if(pre.size() < size){
pre.insert(pre.begin(), num);
}else{
// 缺頁則換出隊尾
pre.erase(pre.end()-1);
pre.insert(pre.begin(), num);
}
res.push_back(make_pair(1, vector<int>(pre.begin(), pre.end())));
}
printf("LRU(最近最久未使用)算法:\n");
print(res, lackPageNum, t);
puts("");
puts("");
}
void OPT(){
// <是否缺頁,頁面>
vector<pair<int, vector<int>>> res;
// 上一頁
vector<int> pre;
// 判斷是否缺頁的
bool flag;
// 缺頁數
int lackPageNum = 0;
for(int k = 0; k < v.size(); k++){
int num = v[k];
flag = true; // 是否缺頁
for (int i = 0; i < pre.size(); ++i) {
if(num == pre[i]){
flag = false;
}
}
if(!flag){
res.push_back(make_pair(0, vector<int>(pre.begin(), pre.end())));
continue;
}
lackPageNum++;
if(pre.size() < size){
pre.push_back(num);
}else{
// 最後面的數在v中的位置
int last = -1;
// 最後面的數在pre中的位置
int idx;
// 目前pre[i] 是否存在與v中
bool isExit;
// 缺頁則換出pre中在v序列最後面的或者不在後面的序列的
for (int i = 0; i < pre.size(); ++i) {
isExit = false;
for (int j = k + 1; j < v.size(); ++j) {
if(pre[i] == v[j]){
isExit = true;
if(j > last){
idx = i;
last = j;
}
break;
}
}
// 目前pre[i] 根本不在v中,則直接退出循環
if(!isExit){
idx = i;
break;
}
}
pre.erase(pre.begin() + idx);
pre.insert(pre.begin()+ idx, num);
}
res.push_back(make_pair(1, vector<int>(pre.begin(), pre.end())));
}
printf("OPT(最佳)置換算法:\n");
print(res, lackPageNum, t);
puts("");
puts("");
}
void setToOne(int &num, int idx){
num = num + (1 << idx);
}
// 統一右移
void rightMove(vector<pair<int, int>> & visNum){
// puts("");
for(pair<int, int> &p: visNum){
// printf("%d ", p.second);
p.second = p.second >> 1;
}
// puts("");
}
// 判斷是否在visNum中
bool isExit(vector<pair<int, int>> & visNum, int num){
for(pair<int, int> &p: visNum){
if(p.first == num){
return true;
}
}
return false;
}
// 找到某個數在隊列中的索引
int findIdx(vector<pair<int, int>> & visNum, int num){
for (int i = 0; i < visNum.size(); ++i) {
pair<int, int> p = visNum[i];
if(p.first == num){
return i;
}
}
return -1;
}
// 找到 freq 最小的在 pre 中的位置
int findMinIdx(vector<pair<int, int>> visNum, vector<int> pre){
int id = -1;
int min = (1 << 31) - 1;
for (int i = 0; i < pre.size(); ++i) {
for (int j = 0; j < visNum.size(); ++j) {
pair<int, int> p = visNum[j];
if(pre[i] == p.first && p.second < min){
id = i;
min = p.second;
}
}
}
return id;
}
void LFU(){
vector<pair<int, vector<int>>> res;
vector<int> pre;
// 記錄通路頻率<數, 頻率>
vector<pair<int, int>> visNum;
int lackPageNum = 0;
for (int num: v) {
bool flag = true;
rightMove(visNum);
for (int i = 0; i < pre.size(); ++i) {
if(pre[i] == num){
flag = false;
}
}
if(!flag){
int idx = findIdx(visNum, num);
setToOne(visNum[idx].second, 30);
res.push_back(make_pair(0, vector<int>(pre.begin(), pre.end())));
continue;
}
lackPageNum++;
bool isEx = isExit(visNum, num);
if(pre.size() < size){
pre.push_back(num);
visNum.push_back({num, (1 << 30)});
}else{
if(!isEx){
visNum.push_back({num, (1 << 30)});
}else{
int idx = findIdx(visNum, num);
setToOne(visNum[idx].second, 30);
}
int idx = findMinIdx(visNum, pre);
pre.erase(pre.begin() + idx);
pre.push_back(num);
}
res.push_back(make_pair(1, vector<int>(pre.begin(), pre.end())));
}
printf("LFU(最少使用)置換算法:\n");
print(res, lackPageNum, t);
puts("");
puts("");
}
// 1 3 4 2 5 6 3 4 7
void CLK(){
vector<pair<int, vector<int>>> res;
vector<int> pre;
int vis[t + 5];
int lackPageNum = 0;
bool flag;
// 指針
int idx = 0;
for (int num: v) {
flag = true;
for (int i = 0; i < pre.size(); ++i) {
if(pre[i] == num){
vis[i] = 1;
flag = false;
}
}
if(!flag){
res.push_back(make_pair(0, vector<int>(pre.begin(), pre.end())));
continue;
}
lackPageNum++;
if(pre.size() < size){
pre.push_back(num);
vis[pre.size()-1] = 1;
}else{
while (true){
if(!vis[idx]){
pre.erase(pre.begin() + idx);
pre.insert(pre.begin() + idx, num);
vis[idx] = 1;
idx = (idx + 1) % size;
break;
}
vis[idx] = 0;
idx = (idx + 1) % size;
}
}
res.push_back(make_pair(1, vector<int>(pre.begin(), pre.end())));
}
printf("NRU(最近未用)置換算法:\n");
print(res, lackPageNum, t);
puts("");
puts("");
}
void init1(){
printf("可用實體塊大小:");
scanf("%d", &size);
printf("調入序列長度:");
scanf("%d", &t);
int num;
printf("請輸入調入頁面序列:");
printf("");
for (int i = 0; i < t; ++i) {
scanf("%d", &num);
v.push_back(num);
}
}
void init2(){
ifstream df("../data.txt");
if (!df.is_open()){
cout << "Error opening file";
exit (1);
}
df >> size;
df >> t;
int num;
for (int i = 0; i < t; ++i) {
df >> num;
v.push_back(num);
}
df.close();
}
void init3(){
int a = 1, b = 10;
size = 3;
t = 20;
int num;
for (int i = 0; i < t; ++i) {
num = random(a, b);
v.push_back(num);
}
}
int main(){
// int num = 1;
// setToOne(num, 4);
// cout << num;
// init1();
init2();
// init3();
printf("\n\n\n通路序列:");
for (int i = 0; i < v.size(); ++i) {
printf("%d ", v[i]);
}
puts("");
FIFO();
LRU();
OPT();
LFU();
CLK();
// Test
// vector<pair<int, int>> vp;
// vp.push_back({3, 8});
// rightMove(vp);
// setToOne(vp[0].second, 30);
// cout << vp[0].second;
return 0;
}