1. 程式人生 > 其它 >作業系統實驗-動態分割槽管理

作業系統實驗-動態分割槽管理

技術標籤:作業系統課程實驗c++

實驗內容

(1)動態分割槽管理的主存分配模擬系統的設計—最先適應法、最佳適應法、最壞適應法(選擇1~3種),模擬實現記憶體的分配回收;
(2)能夠輸入給定的記憶體大小,程序的個數,每個程序所需記憶體空間的大小等;
(3)能夠選擇分配或回收操作;並能顯示完成記憶體分配或回收後記憶體空間的使用情況;
(4)能夠顯示程序在記憶體的儲存地址、大小等

實驗程式碼

1,c++
2,ConsoleApplication1.cpp 主函式在此檔案中。用於選擇操作。
3,service.cpp 資料服務層,當然為了偷懶,一些使用者互動操作也放在了這一層(如新增程序,,,)

4,DataStruct.h 其中定義了資料結構。
5, partition.cpp 一個用於記憶體管理的類,其中包括對分割槽的查詢,整理,,,
6,processM.cpp 一個用於程序管理可有可無的類。
ConsoleApplication1.cpp檔案

// ConsoleApplication1.cpp : 此檔案包含 "main" 函式。程式執行將在此處開始並結束。
//
#include <iostream>
#include"service.h"
using namespace std;
int main()
{		
	//初始化記憶體
	InitParS
(); while (1) { cout << "*******************************菜 單********************************" << endl; cout << "----1、顯示分割槽狀態 " << "----2、釋放分割槽 " << "----3、分配分割槽" << endl; cout << "----4、新增程序 "
<< "----5、顯示當前請求程序 " << "----6、顯示可用表" << endl; cout << " 請輸入要執行的選單選項:"; int choice; cin >> choice; switch (choice) { case 1: PriRAMS(); break; case 2: ReleaseParS(); break; case 3: ChooseDisWay(); break; case 4: AddProS(); break; case 5: PriRequestProS(); break; case 6: PriFreeRAMS(); default: break; } } }

DataStruct.h 檔案

#pragma once
#include<string>
using namespace std;
/*
* 資料結構定義檔案
*/
//分割槽表
struct RAM
{
	int partnum;//區號
	int start; //起始地址
	int end; //結束地址
	int length;//分割槽長度
	int status; //分割槽狀態 1表示已使用 0表示未使用
	string processName;//如果該分割槽有程序,則表示該分割槽的程序名稱
	RAM* next;
};

//可用表
struct FREERAM
{
	int freePartNo = -1;	//空閒區號
	int freeLength = -1;	//空閒區長度
	int freeStart = -1;	//空閒區起址
};

//程序表
struct PROCESS 
{
	string proname;//程序的名稱
	int proram; //程序所需要的記憶體空間大小
	int statue; //程序的狀態 1表示已經分配,0表示未分配
};


service.cpp檔案

#include "service.h"
#include<iostream>
#include"DataStruct.h"
#include"partition.h"
#include"processM.h"
using namespace std;

//資料層物件
partition PAR;//記憶體管理
processM PRO; //程序管理

/*
* 列印分割槽表
*/
void PriRAMS()
{
	cout << endl;
	PAR.PrintRAM();
}

/*
* 列印可用表
*/
void PriFreeRAMS()
{
	cout << endl;
	PAR.PrintFreeRAM();
}


/*
* 列印程序請求表
*/
void PriRequestProS()
{
	cout << endl;
	PRO.PrintRequest();
}

/*
* 初始化記憶體
*/
void InitParS()
{
	int totalRAM = 0;
	cout << "請輸入記憶體總大小:";
	cin >> totalRAM;
	PAR.InitRam(totalRAM);
	cout << "初始化記憶體完成" << endl;
	cout << endl;
}



/*
* 向請求表中新增程序
*/
void AddProS()
{
	int num=0;
	cout << endl;
	cout << "----------------------新增程序-----------------------" << endl;
	cout << "輸出要新增的程序個數:";
	cin >> num;
	for (int i = 0; i < num ; i++)
	{
		PROCESS pro;
		cout << i << ":" << endl;
		cout << "程序的名稱:";
		cin >> pro.proname;
		cout << "程序佔用記憶體的大小:";
		cin >> pro.proram;
		pro.statue = 0;
		PRO.AddProcess(pro);
		cout << endl;
	}
}


/*
* 根據方式獲取區號
* way:使用的方法 0:最先適應法; 1:最佳適應法; 2:最壞適應法
* len: 程序長度
* return:區號 (-1:無可用區)
*/
int GetPartnum(int way, int len)
{
	//判斷是否存在可用表
	if (0==PAR.freeNum)
	{
		return -1;
	}
	if (0==way)
	{
		//最先適應法根據首地址,不需要排序,所以直接查詢即可
		return PAR.SerarchFreeRam(len);
	}
	else if (1==way)
	{
		//最佳適應法,需要先將可用表按照遞增排序
		PAR.AscendingOrder();
		return PAR.SerarchFreeRam(len);
	}
	else
	{
		//最壞適應法,需要將可用表按照遞減排序
		PAR.DecreasingOrder();
		//最壞適應演算法,只需要取最大的一個分割槽進行判斷即可	
		if (len < PAR.FreeRam[0].freeLength)
		{
			return PAR.FreeRam[0].freePartNo;
		}		
	}
	return -1;
}


/*
* 分配程序
* way:使用的方法 0:最先適應法; 1:最佳適應法; 2:最壞適應法
*/
void DistributeProS(int way)
{
	//因為最先適應演算法不需要排序,所以可以直接從可用表中進行查詢
	for (int i = 0; i < PRO.ProcessNum; i++)
	{
		int len = PRO.ProRequest[i].proram;

		//根據分配方式獲取可用區的區號
		int partno = GetPartnum(way, len);
		if (-1 != partno)//表示現有可用表,可用為該程序分配空間
		{
			bool result = PAR.DistributeProcess(partno, PRO.ProRequest[i]);
			if (true == result)
			{
				//分配成功後,將該程序標為已分配
				PRO.ProRequest[i].statue = 1;
			}
		}
	}
	//更新程序請求表
	PRO.UpadateRequest();
}


/*
* 讓使用者選擇分配的方法
*/
void ChooseDisWay()
{
	cout << endl;
	int way = 0;
	cout << "------------------分配方法---------------------" << endl;
	cout << "---0:最先適應法---1:最佳適應法---2:最壞適應法---" << endl;
	cout << "輸入分配的方法:";
	cin >> way;
	DistributeProS(way);
}


/*
* 讓使用者選擇要釋放的分割槽
*/
void ReleaseParS()
{
	cout << endl;
	int partno=-1;
	cout << "------------------釋放分割槽------------------" << endl;
	cout << "輸入要釋放分割槽的區號";
	cin >> partno;
	PAR.ReleasePartition(partno);
}

partition.cpp 檔案

/***************************************
類的成員變數
int totalRAM = 0;	//給定的記憶體
	int partitionNum = 0;	//分割槽個數
	int freeNum = 0;//空閒分割槽個數
	
	RAM* ToalRam=NULL;//分割槽表
	FREERAM FreeRam[100]; //空閒(可用)區表
*********/
#include "partition.h"
using namespace std;

/*
* 初始化記憶體
* totalRAM: 記憶體大小
*/
void partition::InitRam(int totalRAM)
{
	this->totalRAM = totalRAM;
	ToalRam = new RAM;
	ToalRam->partnum = 0;
	ToalRam->start = 0;
	ToalRam->length = totalRAM;
	ToalRam->end = totalRAM - 1;
	ToalRam->next = NULL;
	ToalRam->status = 0;

	//更新可用表
	UpadteFreeRam();
}


/*
* 初始化分割槽的區號
*/
void partition::InitpartNo()
{
	RAM* p = ToalRam;
	int i = 0;
	for (  ; p!=NULL ; p=p->next)
	{
		p->partnum = i;
		i++;
	}
	partitionNum = i;	
}


/*
* 更新空閒分割槽,每次改變分割槽表的時候,都需要更新空閒分割槽
*/
void partition::UpadteFreeRam()
{
	//初始化區號
	InitpartNo();
	//初始化空閒表
	for (int i = 0; i <= freeNum; i++) {
		FreeRam[i].freeLength = -1;
		FreeRam[i].freePartNo = -1;
		FreeRam[i].freeStart = -1;
	}	
	freeNum = 0;

	//找出所有空閒區
	for (RAM* p=ToalRam;p!=NULL;p=p->next)
	{
		if (p->status==0)
		{
			FreeRam[freeNum].freeLength = p->length;
			FreeRam[freeNum].freeStart = p->start;
			FreeRam[freeNum].freePartNo = p->partnum;
			freeNum++;
		}
	}
}


/*
* 從可用表中查詢第一個符合條件的分割槽
* len: 可用區的長度大於len
*/
int partition::SerarchFreeRam(int len)
{
	for (int i = 0; i < freeNum; i++)
	{
		if (FreeRam[i].freeLength >= len)
		{
			return  FreeRam[i].freePartNo;
		}
	}
	return -1;
}


/*
* 向指定的分割槽中,分配程序
* partno:分割槽區號
* pro: 需要分配的程序
* return: true 分配成功 ,false 分配失敗
*/
bool partition::DistributeProcess(int partno, PROCESS pro)
{
	for (RAM* p = ToalRam; p != NULL; p = p->next)
	{
		if (p->partnum==partno)
		{
			//如果該分割槽的長度等於程序所需長度,則直接將該分割槽分配給該程序即可
			if (p->length == pro.proram)
			{
				//更新分割槽
				p->status = 1;
				p->processName = pro.proname;
				//更新可用表
				UpadteFreeRam();
				return true;
			}
			else
			{
			//否則,該分割槽的長度大於該程序所需長度
				//將該分割槽的一部分分給該程序,剩下的部分作為一個新的分割槽
				//為新分割槽初始化
				RAM *nram = new RAM;
				nram->next = NULL;
				nram->partnum = 0; //初始化編號,將會在更新可用表中統一編號
				nram->start = p->start + pro.proram;
				nram->end = p->end;          
				nram->length = p->length - pro.proram;
				nram->status = 0;
				nram->next = p->next;

				//將原分割槽的一部分分配給程序
				p->status = 1;
				p->processName = pro.proname;
				p->length = pro.proram;
				p->end = p->start + pro.proram - 1;
				p->next = nram;

				//更新可用表
				UpadteFreeRam();
				return true;

			}
		}
	}
	return false;
}


/*
* 將可用表進行遞減排序
*/
void partition::AscendingOrder()
{
	UpadteFreeRam();
	for (int i = 0; i < freeNum - 1; i++) {
		for (int j = 0; j < freeNum - i - 1; j++) {
			if (FreeRam[j].freeLength > FreeRam[j + 1].freeLength) {
				change(FreeRam[j].freePartNo, FreeRam[j + 1].freePartNo);
				change(FreeRam[j].freeStart, FreeRam[j + 1].freeStart);
				change(FreeRam[j].freeLength, FreeRam[j + 1].freeLength);
			}
		}
	}
}


/*
* 將可用表進行遞減排序
*/
void partition::DecreasingOrder()
{
	UpadteFreeRam();
	for (int i = 0; i < freeNum - 1; i++) {
		for (int j = 0; j < freeNum - i - 1; j++) {
			if (FreeRam[j].freeLength < FreeRam[j + 1].freeLength) {
				change(FreeRam[j].freePartNo, FreeRam[j + 1].freePartNo);
				change(FreeRam[j].freeStart, FreeRam[j + 1].freeStart);
				change(FreeRam[j].freeLength, FreeRam[j + 1].freeLength);
			}
		}
	}
}


/*
* 釋放指定分割槽
* partno:要釋放的分割槽的區號
*/
void partition::ReleasePartition(int partno)
{
	for (RAM* p = ToalRam; p != NULL; p = p->next)
	{
		if (p->partnum == partno)
		{
			p->status = 0;
			p->processName ="";
			break;
		}
	}
	//處理回收區與空閒區鄰接
	NeatenDebris();
}

/*
* 整理記憶體
* 當釋放分割槽後,呼叫該函式用於處理空閒區與回收取鄰接的情況*/
void partition::NeatenDebris()
{
	for (RAM* p = ToalRam; p != NULL; )
	{
		if (p->status == 0 && p->next != NULL) {
			if (p->next->status == 0) {
				p->end = p->next->end;
				p->length = p->length + p->next->length;

				RAM* q = p->next;
				p->next = q->next;
				delete q;
			}
			else {
				p = p->next;
			}
		}
		else {
			p = p->next;
		}
	}
	//跟新可用區
	UpadteFreeRam();
}



/*
* 列印分割槽表
*/
void partition::PrintRAM()
{
	cout << "-------------------分割槽表---------------------" << endl;
	cout << "區號\t首址\t尾址\t長度\t狀態\t佔用程序編號" << endl;
	int i = 0;
	for (RAM* p = ToalRam; p != NULL;p=p->next) {
		cout << " " << p->partnum << "\t" << p->start << "\t" << p->end << "\t" << p->length << "\t";
		if (p->status == 1)
			cout << "佔用\t" << p->processName << endl;
		else
			cout << "空閒" << endl;
		i++;
	}
	cout << endl;
}


/*
* 列印可用表
*/
void partition::PrintFreeRAM()
{
	cout << "-------------------------可用表資訊-----------------------" << endl;
	cout << "區號\t分割槽長度\t首地址" << endl;
	for (int i = 0; i < freeNum; i++)
	{
		cout << FreeRam[i].freePartNo << "\t" << FreeRam[i].freeLength << "\t" << FreeRam[i].freeStart << endl;
	}
}



/*
* 交換a與b的值,
*用於可用表排序的工具函式
*/
void partition::change(int& a, int& b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

processM.cpp檔案

/****************************
類的成員變數:
PROCESS ProRequest[100]; //程序請求表
int ProcessNum = 0;//請求表中程序個數
**********************************/
#include "processM.h"
#include<iostream>
using namespace std;
/*
* 新增程序到程序請求表中
*/
void processM::AddProcess(PROCESS pro)
{
	ProRequest[ProcessNum] = pro;
	ProcessNum++;
}

/*
* 列印請求表
*/
void processM::PrintRequest()
{
	cout << "---------------------程序請求表----------------------" << endl;
	cout << "程序名稱\t程序大小" << endl;
	for (int i = 0; i < ProcessNum; i++) {
		cout <<  ProRequest[i].proname << "\t\t" << ProRequest[i].proram << endl;
	}
}

/*
* 更新程序請求表
*/
void processM::UpadateRequest()
{
	int k = 0;
	for (int i = 0; i < ProcessNum; i++)
	{
		if (ProRequest[i].statue!=1)
		{
			ProRequest[k].proname = ProRequest[i].proname;
			ProRequest[k].proram = ProRequest[i].proram;
			ProRequest[k].statue = ProRequest[i].statue;
			k++;
		}
	}
	ProcessNum = k;
}