1. 程式人生 > >作業系統缺頁中斷FIFO、LRU、OPT演算法實現(對於頁框數量可以由使用者調控)

作業系統缺頁中斷FIFO、LRU、OPT演算法實現(對於頁框數量可以由使用者調控)

在之前,筆者隨意的用針對固定的三個頁框的情況下寫了一份兒基本程式碼,也就是熟悉一下演算法原理,大家可以忽略。

這一次寫的是實現使用者對於頁框數量實現自由的調控。

注意的是筆者使用的是C/C++的陣列,所以為了避免麻煩,在程式碼開始寫了一個#define max 5,當然對於這裡的5大家可以自己調整,由於手中的測試資料是12個數的陣列,所以這裡對於很多迴圈中都直接用了12,這是可以自由更改的,大家需要的時候可以自己實現或者用引數傳遞。演算法本身很簡單,只要稍微注意一下細節就行。廢話不多說,直接貼程式碼。

// Exercise4.cpp: 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <iostream>
using namespace std;
#define max 5
int pageList[12] = {4,3,2,1,4,3,5,4,3,2,1,5};

int checkPage(int page, int Page[], int k) {
	for (int i = 0;i < k;i++)
		if (page == Page[i])
			return i;
	return -1;
}

/*前向查詢最近出現的頁面*/
int frontSearchPage(int page, int i) {
	for (int j = 0;j < i;j++)
		if (page == pageList[j])
			return j;
	return i;
}

int backSearchPage(int page, int i) {
	for (int j = i;j >= 0;j--)
		if (page == pageList[j])
			return j;
	return -1;
}

/*在pageList中查詢一個頁面*/
int searchPage(int page, int i) {
	i++;
	for(;i < 12;i++)
		if (pageList[i] == page) {
			return i;
		}
	return 999;
}

/*在pageList中統計頁面出現的次數*/
int countPage(int page, int i) {
	int count = 0;
	for (int j = i;j >= 0;j--)
		if (pageList[j] == page)
			count++;
	return count;
}

/*列印演算法*/
void display(int k, int *Spage[], int count, char empty[]) {
	cout << "List: \t";
	for (int i = 0;i < 12;i++)
		cout << pageList[i] << "\t";
	cout << endl;
	for (int i = 0;i < k;i++)
	{
		cout << "page" << i + 1 << ": \t";
		for (int j = 0;j < 12;j++) {
			if (Spage[i][j] != -1)
				cout << Spage[i][j] << "\t";
			else
				cout << "\t";
		}
		cout << endl;
	}
	cout << endl << "empty :\t";
	for (int i = 0;i < 12;i++)
		cout << empty[i] << "\t";
	cout << endl;
	cout << endl << "共缺頁: " << count << "次" << endl;
}

/*先進先出演算法*/
void FIFO(int k) {
	int page[max];
	int *sPage[max];
	for (int i = 0; i < max;i++) {
		if (i < k)
		{
			sPage[i] = new int[12];  //對使用的區域進行記憶體分配,可增加項則不考慮
			page[i] = -1;    //-1表示在本實驗中需要用到的
		}
		else
			page[i] = -2;   //-2表示可增加項
	}
	int count = 0;
	char empty[12];
	for (int i = 0;i < 12;i++) {
		empty[i] = 'F';
		for (int j = 0;j < k;j++)
			sPage[j][i] = -1;
	}
	for (int i = 0;i < 12;i++) {
		int num = checkPage(pageList[i], page, k);
		if (num >= 0) {
			for (int j = 0;j < k;j++)
				sPage[j][i] = sPage[j][i - 1];
			continue;
		}
		else {
			for (int j = k - 1;j > 0;j--)
				page[j] = page[j - 1];
			page[0] = pageList[i];
			for (int j = 0;j < k;j++)
				sPage[j][i] = page[j];
			empty[i] = 'T';
			count++;
		}
	}
	display(k, sPage, count, empty);
}

/*OPT演算法*/
void OPT(int k) {
	int page[max];
	int *sPage[max];
	int count = 0;
	char empty[12];
	for (int i = 0; i < max;i++) {
		if (i < k)
		{
			sPage[i] = new int[12];  //對使用的區域進行記憶體分配,可增加項則不考慮
			page[i] = -1;    //-1表示在本實驗中需要用到的
		}
		else
			page[i] = -2;   //-2表示可增加項
	}
	for (int i = 0;i < 12;i++) {
		empty[i] = 'F';
		for (int j = 0;j < k;j++)
			sPage[j][i] = -1;
	}
	sPage[0][0] = pageList[0];
	page[0] = pageList[0];
	count++;
	empty[0] = 'T';
	for (int i = 1;i < 12;i++) {
		int num = checkPage(pageList[i], page, k);
		if (num >= 0) {
			for (int j = 0;j < k;j++)
				sPage[j][i] = sPage[j][i - 1];
			continue;
		}
		else {
			int j;
			for(j = 1;j < k;j++)
				if (page[j] == -1) {
					for (int l = j;l > 0;l--) {
						page[l] = page[l - 1];
						sPage[l][j] = page[l];
					}
					sPage[0][i] = pageList[i];
					page[0] = pageList[i];
					break;
				}
			if (j == k) {
				int pageLoc[max];
				for (int l = 0;l < k;l++) {
					pageLoc[l] = searchPage(page[l], i);
				}
				int far = 0;
				for (int l = 0;l < k;l++) {
					if (pageLoc[far] < pageLoc[l])
						far = l;
				}
				for (int l = far;l > 0;l--)
					page[l] = page[l - 1];
				page[0] = pageList[i];
				for (int l = 0;l < k;l++) {
					sPage[l][i] = page[l];
				}
			}
			count++;
			empty[i] = 'T';
		}
	}
	display(k, sPage, count, empty);
}

/*LRU演算法*/

void LRU(int k) {
	int page[max];
	int *sPage[max];
	int count = 0;
	char empty[12];
	for (int i = 0; i < max;i++) {
		if (i < k)
		{
			sPage[i] = new int[12];  //對使用的區域進行記憶體分配,可增加項則不考慮
			page[i] = -1;    //-1表示在本實驗中需要用到的
		}
		else
			page[i] = -2;   //-2表示可增加項
	}
	for (int i = 0;i < 12;i++) {
		empty[i] = 'F';
		for (int j = 0;j < k;j++)
			sPage[j][i] = -1;
	}
	sPage[0][0] = pageList[0];
	page[0] = pageList[0];
	count++;
	empty[0] = 'T';
	for (int i = 1;i < 12;i++) {
		int countpage[max];
		int num = checkPage(pageList[i], page, k);
		if (num >= 0) { //頁面處於該佇列中
			for (int j = 0;j < k;j++)
				sPage[j][i] = sPage[j][i - 1];
			for (int l = 0; l < k && sPage[l][i] != -1;l++) {
				for (int j = 0;j < k && sPage[j][i] != -1;j++) {
					int d1 = backSearchPage(page[l], i);
					int d2 = backSearchPage(page[j], i);
					if (d1 > d2) {
						int temp = page[l];
						page[l] = page[j];
						page[j] = temp;
					}
				}
			}
			for (int l = 0;l < k;l++)
				sPage[l][i] = page[l];
			continue;
		}
		else {
			count++;
			empty[i] = 'T';
			//對原始佇列中的頁面按照順序排列:
			//排序機制:1.讓出現次數較多的排在前列,2.在同等次數的情況下,讓最後一次出現靠後的排在前列
			for (int l = 0;l < k && sPage[l][i] != -1;l++)
				countpage[l] = countPage(page[l], i);
			int far = 0;
			for (int l = 0; l < k && sPage[l][i] != -1;l++) {
				for (int j = 0;j < k && sPage[j][i] != -1;j++) {
					if (countpage[l] < countpage[j]) {
						int temp = page[l];
						page[l] = page[j];
						page[j] = temp;
					}
					else if (countpage[l] == countpage[j]) {
						int d1 = frontSearchPage(page[l], i);
						int d2 = frontSearchPage(page[j], i);
						if (d1 < d2) {
							int temp = page[l];
							page[l] = page[j];
							page[j] = temp;
						}
					}
				}
			}
			for (int l = k - 1;l > 0;l--)
				page[l] = page[l - 1];
			page[0] = pageList[i];
			for (int l = 0;l < k;l++)
				sPage[l][i] = page[l];

		}
	}
	display(k, sPage, count, empty);
}


int main()
{
	int k;
	while (1) {
		cout << "輸入需要的頁框數(max = 5,輸入6退出): ";
		cin >> k;
		if (k == 6) {
			cout << "感謝使用" << endl;
			exit(0);
		}
		else {
			cout << "FIFO演算法: " << endl;
			FIFO(k);
			cout << endl;
			cout << "OPT演算法: " << endl;
			OPT(k);
			cout << endl;
			cout << "LRU演算法: " << endl;
			LRU(k);
		}
	}
    return 0;
}