作業系統實驗-動態分割槽管理
阿新 • • 發佈:2020-12-15
實驗內容
(1)動態分割槽管理的主存分配模擬系統的設計—最先適應法、最佳適應法、最壞適應法(選擇1~3種),模擬實現記憶體的分配回收;
(2)能夠輸入給定的記憶體大小,程序的個數,每個程序所需記憶體空間的大小等;
(3)能夠選擇分配或回收操作;並能顯示完成記憶體分配或回收後記憶體空間的使用情況;
(4)能夠顯示程序在記憶體的儲存地址、大小等
實驗程式碼
1,c++
2,ConsoleApplication1.cpp 主函式在此檔案中。用於選擇操作。
3,service.cpp 資料服務層,當然為了偷懶,一些使用者互動操作也放在了這一層(如新增程序,,,)
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;
}