作業系統——c++實現頁式虛擬儲存管理

~A~發表於2020-11-10

整體思路:先在頁表裡找邏輯地址所在的頁號,如果找不到,就發生缺頁中斷,通過先進先出演算法進行對頁的置換,將所需的頁調入記憶體中,並更新頁表。

#include <iostream>
#define n 64   //分配給程式最大的頁的總數
#define length 10   //記憶體塊的最大個數 
using namespace std;

//定義頁的結構體 
struct{       
	//下標為頁號 
	int flag;   //1表示在當前頁記憶體裡面,0表示表示當前頁在外存 
	int pnumber;  //記憶體地址(物理塊號) 
	int write;   //修改位  
	int dnumber;   //外存地址(物理塊好) 
}page[n];   //注意,這不是頁表,是程式所擁有的最大頁數,包括利用的和未利用的,利用的又分為被調入記憶體裡的和在外存裡的 
int m;    //頁表的長度 
int page_length;  //程式所利用的最大頁數,也就是程式真實佔用的頁數 
int p[length];   //維護頁進入記憶體的順序,用來實現先進先出的置換演算法 
int head;   //指向記憶體最早進入的頁號 

int page_interrupt(int lnumber){
	int j;
	cout << "發生缺頁中斷" << lnumber <<endl;
	j = p[head];  //取當前最早進入記憶體的頁號,利用先進先出演算法 
	//將頁j從記憶體調出,並將lnumber從磁碟調入記憶體
	page[j].flag = 0;  //調出記憶體 
	page[lnumber].pnumber = page[j].pnumber;  //將頁j所佔用的記憶體分配給lnumber 
	page[lnumber].flag = 1;
	page[lnumber].write = 0; 
	cout<< "淘汰記憶體塊" <<page[j].pnumber<< "中的頁" << j << ",從磁碟第" << page[lnumber].dnumber << "塊中調入頁" << lnumber << endl;
	//更新陣列p 
	p[head] = lnumber;  //更新為當前進入記憶體的頁號  
	head = (head + 1) % m;  //更新指向當前記憶體最早的頁號 
	return 1;
}

int command(unsigned laddress, int write){  
	unsigned paddress, ad, pnumber, lnumber;
kk: lnumber = laddress >> 10;  //取頁號左移10位,說明頁面大小為2^10=1024,這裡可以直接等於 laddress / 1024
	ad = laddress & 0x3ff;   //取偏移地址,可以直接寫成  laddress % 1024
	if(lnumber >= page_length){
		cout << "不存在該頁" << endl;
		return 0;
	}
	if(page[lnumber].flag == 1){  //說明當前頁在記憶體,也就是當前頁在頁表裡面
		pnumber = page[lnumber].pnumber;  //通過頁表的對映找到在記憶體物理塊號 
		paddress = (pnumber << 10) | ad;  //將物理塊好和偏移地址進行拼接,可以寫成 pnumber * 1024 + ad;
		cout<<"邏輯地址是:"<<laddress<<"對應實體地址是:"<<paddress<<endl;
		if(write == 1){  //修改 
			page[lnumber].write = 1;
		}
	}else{  //當前頁不在記憶體,則進行缺頁中斷,並將lnumber也從外存調入記憶體
		page_interrupt(lnumber);
		goto kk;  //跳轉到標號kk,進行邏輯地址->實體地址的轉換 
	}
	return 1;
}

int main(){
	int flag, pnumber, write, dnumber;
	unsigned laddress;  //邏輯地址
	int i;
	cout << "輸入頁表的資訊,建立頁表!!!" << endl;
	i = 0;  //頁號 
	while(1){
		cout << "外存的物理塊號(輸入-1結束):";
		cin >> dnumber;
		if(dnumber == -1) break;
		page[i].flag = 0;  //表示當前頁在外存 
		page[i].write = 0;
		page[i].dnumber = dnumber;
		i++; 
	}
	page_length = i;  //初始化程式所利用的頁的總數
	m = 0;
	while(1){
		cout<< "輸入記憶體塊號、記憶體塊數要小於" << page_length << ",(以-1結束):";
		cin >> pnumber;
		if(pnumber == -1) break;
		if(m < i){
			page[m].pnumber = pnumber;
			page[m].flag = 1;  //表示當前頁在記憶體 
			p[m] = m;  //預設頁是按頁號遞增進入記憶體 
			m++;
		}
	} 
	while(1){
		cout<<"輸入指令性質(1-修改,0-不需要,其他-結束程式執行)和邏輯地址:";
		cin>>write;
		if(!(write==0||write==1)) break;
		cin >> laddress;   //輸入邏輯地址
		command(laddress, write); 
	}
	return 0;
}

相關文章