操作系統-動態分區式存貯區管理

報告下載:地址。。(絕對原創,請勿抄襲)

()、程序功能:模擬動態分區式存貯區管理

()、設計思路:

1、設計一個動態分區式存貯區管理程序,支持不同的放置策略。如首次、最佳、最壞。

2、分區描述器中爲 flag/size/next;

3、自由主存隊列按鏈表組織,主存大小假設爲maxsize(單位爲節=rd的大小)。

4、作業申請n,實際分配的分區大小應爲n+1節。 其中一節作爲分區描述器,其他n節提供給作業。

5、已分配區放在高地址處。

6、合併時應考慮四種情況:

假設回收區爲r,上鄰爲f1f1需搜索自由主存隊列),下鄰爲f2f2可直接計算)

A) f1空閒,f2已分配;

B) f1已分配,f2空閒;

C) f1空閒,f2空閒;

D) f1已分配,f2已分配;

()、數據結構

1PCB(進程控制器)

私有數據成員

類型

名稱

註釋

int

begin

進程開始的首地址

int

size

進程佔用的大小

string

name

進程名

函數

聲明

註釋

PCB(string n="'",int s=0,int b=0)

構造函數

ostream& operator<<(ostream&os, PCB&P)

重定義輸出函數

注:PCB類是manage類的友元類。

2block(分區描述器)

私有數據成員

類型

名稱

註釋

int

m_size

分區的大小

bool

m_falg

判斷該分區是否被佔用

block*

next

下一個分區的地址

函數

函數聲明

註釋

block(bool flag = false… …)

構造函數

ostream& operator<<(ostream&os, block&P)

重定義輸出函數

注:block類是manage類的友元類。

3manage

私有數據成員

類型

名稱

註釋

block*

first;

分區鏈表首地址

vector<PCB>

lib;

未結束的所有進程

函數 

聲明

註釋

manage()

構造函數

void first_time();

首次適應算法

void best();

最佳適應算法

void worst();

最壞適應算法

void free();

內存回收

void show();

顯示內存分配情況

 

()、算法設計

1、首次適應算法

首次適應算法是將程序放入到主存中,按地址查找到第一個能裝入它的空閒區。在首次適應算法中,空閒區是按其位置的順序鏈接在一起,即每一個後繼空閒去的起始地址總比他前者大。當要分配一個分區時,總是從低地址空閒區開始查尋,直到找到第一個足以滿足該程序要求的空閒區爲止。

代碼:

void manage::first_time() {

	cout << "輸入進程名和大小:";
	string name; int size,addr(0);
	cin >> name >> size;
	block* p(first);

	while (p != nullptr) {						//尋找塊
		addr +=(p->m_size+1);					//計算地址
		if (p->m_flag == false) {				//當前塊未被佔用
			if (p->m_size > size) {			//當前塊的大小大於進程申請的大小
				p->m_size -= (size + 1);		//從當前塊中減去進程申請的大小
				block* temp=new block(true,size,p->m_next);	//新建一個進程塊
				p->m_next = temp;				//添加到當前塊的後面
				addr -= (size + 1);			//重新計算當前塊的地址
				break;
			}
			else if (p->m_size == size) {	//當前塊的大小剛好夠進程申請的大小
				p->m_flag = true;			//直接更改當前塊的狀態爲已佔用,不用分裂塊
				addr -= (size + 1);		//重新計算地址
				break;
			}
			else p = p->m_next;		//當前塊的大小不滿足進程申請的大小,先後繼續尋找。
		}
		else p = p->m_next;				//當前塊已被佔用,先後繼續尋找
	}
	if (p == nullptr)cout << "分配失敗" << endl;	//未找到符合條件的塊,分配失敗
	else {								//找到符合條件的塊,該進程存入lib進程庫中
		PCB temp(name, size, addr);
		lib.push_back(temp);
	}
}


2、最佳適應算法

最佳適應算法是將程序放入主存中與他所需大小最接近的空閒區中,在最佳適應算法中,空閒區隊列是按空閒區大小遞增順序鏈接在一起的。在進行分配時總是從最小的空閒區開始查尋,因而找到的第一個能滿足要求的空閒區便是最佳的一個。即從所要求的大小來看,該區和氣候的所有空閒區相比它是最接近的。
代碼:

void manage::best() {

	cout << "輸入進程名和大小:";
	string name; int size, addr1(0),addr2(0);
	cin >> name >> size;
	block *p(first),*q(nullptr);
	int Error(512);

	while (p != nullptr) {
		addr1 += (p->m_size + 1);
		if (p->m_flag == false) {		//當前塊未被佔用
			if (p->m_size > size) {	//當前塊的大小滿足進程請求的大小
				if (p->m_size - size < Error) {	//當前塊更合適該進程
					Error = p->m_size - size;	//計算偏差
					q = p;			//保存當前塊的地址
					addr2 = addr1 - size - 1;
					p = p->m_next;	//指針後移
				}
				else p = p->m_next;	//和之前的塊相比,之前的塊更合適該進程
			}
			else if (p->m_size == size) {	//當前塊的大小剛好等於進程申請的大小
				q = p;				//已找到最合適的塊,保存當前塊的信息並退出
				addr2 = addr1 - size - 1;
				Error = 0;
				break;
			}
			else p = p->m_next;		//當前塊的大小小於進程請求的大小,繼續先後搜索
		}
		else p = p->m_next;			//當前塊已經被佔用,繼續先後搜索
	}
	if (Error == 512)cout << "分配失敗" << endl;
	else {
		if (Error == 0)q->m_flag = true;
		else {
			q->m_size -= (size + 1);	//從當前塊中減去進程申請的大小
			block* temp = new block(true, size, q->m_next);	//新建一個進程塊
			q->m_next = temp;			//添加到當前塊的後面
		}
		PCB temp(name, size, addr2);
		lib.push_back(temp);
	}
}


3、最壞適應算法

最壞適應算法就是將程序放入主存中最不適合它的空閒區,即最大的空閒區內。在最壞適應算法中,空閒區是按大小遞減順序連接到一起的,因此,其隊列指針總是指向最大空閒區,在進行分配時,總是從最大空閒區開始查尋。

代碼:

void manage::worst() {

	cout << "輸入進程名和大小:";
	string name; int size, addr1(0), addr2(0);
	cin >> name >> size;
	block *p(first), *q(nullptr);
	int Error(0);

	while (p != nullptr) {
		addr1 += (p->m_size + 1);
		if (p->m_flag == false) {		//當前塊未被佔用
			if (p->m_size >= size) {	//當前塊的大小滿足進程請求的大小
				if (p->m_size - size >= Error) {//當前塊比之前塊更大
					Error = p->m_size - size;	//計算偏差
					q = p;			//保存當前塊的地址
					addr2 = addr1 - size - 1;
					p = p->m_next;	//指針後移
				}
				else p = p->m_next;	//和之前的塊相比,之前的塊更合適該進程
			}
			else p = p->m_next;		//當前塊的大小小於進程請求的大小,繼續先後搜索
		}
		else p = p->m_next;			//當前塊已經被佔用,繼續先後搜索
	}
	if (Error == 0)cout << "分配失敗" << endl;
	else {
		q->m_size -= (size + 1);		//從當前塊中減去進程申請的大小
		block* temp = new block(true, size, q->m_next);	//新建一個進程塊
		q->m_next = temp;				//添加到當前塊的後面
		PCB temp1(name, size, addr2);
		lib.push_back(temp1);
	}
}


4、內存回收

在內存回收時應考慮四種情況:

假設回收區爲r,上鄰爲f1f1需搜索自由主存隊列),下鄰爲f2f2可直接計算)

A) f1空閒,f2已分配:rf1合併

B) f1已分配,f2空閒:rf2合併

C) f1空閒,f2空閒:rf1f2合併

D) f1已分配,f2已分配:r不和任何分區合併

代碼:

void manage::free() {
	cout << "輸入回收進程的名稱:";
	string name;
	cin >> name;

	//在lib庫中查找是否存在該進程
	vector<PCB>::iterator it = lib.begin();
	while (it != lib.end()){
		if (it->name == name)
			break;
		else it++;
	}
	//該進程不存在,直接提示並退出函數
	if (it == lib.end()) {
		cout << "該進程不存在" << endl;
		return;
	}
	//進程存在
	else {
		int addr(0); block *p(first);
		while (p != nullptr) {					//查找該進程所佔用的內存塊
			if (it->begin == addr)break;		//查找到該進程
			addr += (p->m_size + 1);
			p = p->m_next;
		}
		if (p == nullptr)cout << "未在內存中查找到該進程" << endl;
		else {
			p->m_flag = false;				//該內存塊的狀態更改爲未佔用
	
			//所回收的內存塊後面存在空閒的內存塊
			if (p->m_next != nullptr&&p->m_next->m_flag==false) {
				p->m_size += p->m_next->m_size;//該內存塊的大小增加爲爲倆內存大小之和
				block *temp(p->m_next);
				p->m_next = p->m_next->m_next;	//更改指針指向
				delete temp;					//釋放後一指針的空間
			}
			lib.erase(it);						//進程庫中刪除當前進程

			//所回收的內存塊前面存在空閒的內存塊
			block *q(first);
			//尋找到所回收的內存塊前面的內存塊
			while (q != nullptr) {
				//所回收的內存塊前面存在空閒的內存塊
				if (q->m_next==p&&q->m_flag == false) {	
					q->m_size += (p->m_size + 1);
					q->m_next = p->m_next;
					delete p;
					break;
				}
				q = q->m_next;
			}
		}
	}
}


()、程序運行情況

1、測試數據:初始值大小爲512(分區描述器佔一位,實際大小爲511)

2、測試結果:

(1)、首次適應算法

 

(2)、最佳適應算法





(3)、最差適應算法

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章