操作系统课内实践:内存管理

Posted 拾年之璐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了操作系统课内实践:内存管理相关的知识,希望对你有一定的参考价值。



本文记录 WHUT-计算机学院-操作系统 课程 课内实践:内存管理

纸上得来终觉浅,觉知此事需躬行!


1、实验内容:

实验预备:掌握内存管理的相关内容,对内存的分配与回收有深入的理解。

实验内容:模拟实现内存管理机制

具体要求:


  • 任选一种计算机高级语言编程实现
  • 选择一种内存管理方案:动态分区式、请求页式、段式、段页式等
  • 能够输入给定的内存大小,进程的个数,每个进程所需内存空间的大小等
  • 能够选择分配 / 回收操作
  • 能够显示进程在内存的存储地址、大小等
  • 显示每次完成内存分配或回收后内存空间的使用情况

2、运行结果:

首先输入基本信息:

【操作系统】课内实践:内存管理_武汉理工

然后对其中某个分区进行释放操作,假设选择3号区,结果如下:

【操作系统】课内实践:内存管理_操作系统_02

继续对上面分区表的2号区释放内存操作,按照程序要求,释放的2号要与空闲分区3号合并,合并后空闲长度应为二者之和,即22,结果如下图:

【操作系统】课内实践:内存管理_武汉理工_03

下面进行添加进程操作,假设添加如下的进程号、进程长度:

A  15  ,  B  1  ,C  10

然后采用最先适应算法分配分区,运行结果如下图:

【操作系统】课内实践:内存管理_i++_04

然后将上图中的1号区、2号区的内存释放,分区表信息如下:

【操作系统】课内实践:内存管理_OS_05

这时,添加4个进程:

D 6;E 18;F 25;G 4

本次采用最佳适应算法,运行结果如下图:

【操作系统】课内实践:内存管理_内存管理_06

这时,将:0、3、6、7四个分区的进程释放,分区边信息如下:

【操作系统】课内实践:内存管理_武汉理工_07

此时,请求表中还有进程G需要请求4个长度的内存信息;

再次基础上,增加进程:  H 25  ;  I 3  ;  K 18

增加之后,请求表中的信息应该是下图这样的:

【操作系统】课内实践:内存管理_操作系统_08

本次采用最坏适应算法,运行结果如下:

【操作系统】课内实践:内存管理_OS_09

3、实验源码:


本次实践难度不大,建议自行完成!

下面代码是使用C++、链表实现!


#include <iostream>
#include <string>
using namespace std;

int processNum = 0;//进程个数
int totalRAM = 0; //给定的内存

//分区表
int partitionNum=0; //分区个数
struct RAM
int processNo; //进程编号
int start=0; //首址
int length=0; //长度大小
int end=0; //结束
int status=0; //分区状态
;
RAM ram[100];//下标i表示区号

//可用表
int freeNum=0;//空闲分区个数
struct FREERAM
int freePartNo=-1; //空闲区号
int freeLength=-1; //空闲区长度
int freeStart=-1; //空闲区起址
;
FREERAM freePart[100];//空闲分区表,可用表

//请求表
int reqNum=0;//请求进程个数
struct REQUEST
string reqProcessNo; //请求进程名
int reqLength; //请求进程长度
int reqed=0; //请求进程状态(即是否分配处理)
;
REQUEST request[100];

//分区表
struct RamNode
int partNo; //每个节点都是一个分区,有一个区号,默认从0开始
string processNo; //如果被占用,则显示被占用的进程编号
int start = 0; //分区首址
int length = 0; //分区长度大小
int end = 0; //分区尾址
int status = 0; //分区状态
RamNode *next; //下一个分区
;
typedef RamNode *ramNode;
ramNode head = NULL, tail = NULL, p, q;

//输出分区表
void printDongtai();

//初始化
void InitDongtai()
cout<< "*******初始化******" <<endl;
cout << " 请输入内存总大小:";
cin >> totalRAM;
cout << " 请输入进程个数:";
cin >> processNum;
cout << " 请输入进程 1到" << processNum << " 所需要的内存空间:";
for (int i = 0; i < processNum; i++)
int tempRam = 0;
cin >> tempRam;

//看一下能不能放下第 i 个进程
if (i==0 && tempRam < totalRAM)
p = new RamNode;
p->partNo = i; //节点区号
p->processNo = to_string(i + 1); //占用进行号
p->start = 0; //起址
p->length = tempRam; //长度
p->end = p->start + p->length - 1; //终址
p->status = 1; //状态
p->next = NULL;

partitionNum++;

if (head == NULL)
head = p; q = p;

else
q->next = p;
q = p;


else if(tempRam+q->end<totalRAM)
p = new RamNode;
p->partNo = i;
p->processNo =to_string(i + 1);
p->start = q->end + 1;
p->length = tempRam;
p->end = p->start + p->length - 1;
p->status = 1;
p->next = NULL;

partitionNum++;

if (head == NULL)
head = p;
q = p;

else
q->next = p;
q = p;


//放不下了o(╥﹏╥)o进入请求队列吧,等会儿写
else
request[reqNum].reqProcessNo = to_string(i + 1);
request[reqNum].reqLength = tempRam;
reqNum++;


//如果分配总内存有剩余,最后剩余空间也是一个分区
if (q->end < totalRAM - 1)
p = new RamNode;
p->partNo = q->partNo + 1;
p->start = q->end + 1;
p->end = totalRAM - 1;
p->status = 0;
p->next = NULL;
p->length = totalRAM - p->start ;
if (head == NULL)
head = p;
q = p;

else
q->next = p;
q = p;



//尾指针,先放着,应该有用,(⊙o⊙)…最终没用到
tail = p;


//初始化分区的区号,每次当改变链表结构的时候,都要运行一次。
void InitpartNo()
int i = 0;
for (p = head; p != NULL; p=p->next)
p->partNo = i;
i++;



//给出第i个请求任务的插入点p,实现链表插入
void insert(ramNode &p,int i)
p->processNo = request[i].reqProcessNo;
p->status = 1;
//如果请求长度等于空闲长度,最好不过了
if (request[i].reqLength == p->length)
//请求<空闲,需要分割了o(╥﹏╥)o
else
q = new RamNode;
q->end = p->end;
p->end = p->start + request[i].reqLength - 1;
p->length = request[i].reqLength;

q->partNo = p->partNo + 1;
q->start = p->end + 1;
q->length = q->end - q->start + 1;
q->status = 0;

q->next = p->next;
p->next = q;

//修改请求表请求进程状态为 已分配
request[i].reqed = 1;


/*最先适应算法*/
void zuixianSuanfa(int &i)
for (i; i < reqNum; i++)
//按空闲分区首地址递增
for (p = head; p != NULL; p = p->next)
//如果当前请求进程请求长度小于最先找到的空闲分区长度,则进行分配
if (request[i].reqLength <= p->length && p->status == 0)
insert(p, i);
break;


//第1个请求进程,遍历完链表,仍然找不到内存去,直接返回。
if (i == 0 && p == NULL)
return;

else if (p == NULL)
return;




/*更新请求表信息,已经分配的进程取出*/
void refeshReq(int i)
int temp = reqNum;
reqNum = reqNum - i;
for (int j = 0; j < temp; i++, j++)
request[j].reqProcessNo = request[i].reqProcessNo;
request[j].reqLength = request[i].reqLength;
request[j].reqed = request[i].reqed;




/*最先适应算法*/
void zuixian()
cout<<"当前请求表信息如下:"<<endl;
cout<<"顺序\\t进程名\\t请求长度"<<endl;
for (int i = 0; i < reqNum; i++)
cout << i+1 <<"\\t" << request[i].reqProcessNo << "\\t" << request[i].reqLength << endl;

int i=0;
zuixianSuanfa(i);
//未做任何分配,直接返回
if (i == 0)
cout << "该策略下空间不足,未做任何分配!" << endl;
return;

//全部分配完毕
else if (i == reqNum)
cout << "请求表中的进程全部分配完毕!" << endl;

//只完成部分分配
else
cout << "请求表中的进程部分分配完毕!剩余未分配进程如下:" << endl;
cout << "\\t进程名\\t请求长度" << endl;
for (int i = 0; i < reqNum; i++)
if (request[i].reqed == 0)
cout << "\\t" << request[i].reqProcessNo << "\\t" << request[i].reqLength << endl;



cout << "分配后内存使用情况如下:" << endl;
printDongtai();
InitpartNo();
//对请求表数据更新(删除)
refeshReq(i);
return;


/*交换a和b的值*/
void change(int &a,int &b)
int temp;
temp = a;
a = b;
b = temp;


/*找出所有的空闲分区,并放在空闲分区表中*/
void findFreePart()
InitpartNo();//初始化一下
//初始化空闲表
for (int i = 0; i <= freeNum; i++)
freePart[i].freePartNo = -1;
freePart[i].freeStart = -1;
freePart[i].freeLength = -1;

freeNum = 0;
//先揪出那些空闲分区
for (p = head; p != NULL; p = p->next)
//空闲状态分区,进入可用表
if (p->status == 0)
freePart[freeNum].freePartNo = p->partNo;
freePart[freeNum].freeStart = p->start;
freePart[freeNum].freeLength = p->length;
freeNum++;




/*对找出所有空闲区进行排序:递增*/
void InitZuijia()
findFreePart();
//按空闲分区大小递增排序
for (int i = 0; i < freeNum - 1; i++)
for (int j = 0; j < freeNum - i - 1; j++)
if (freePart[j].freeLength > freePart[j + 1].freeLength)
change(freePart[j].freePartNo, freePart[j + 1].freePartNo);
change(freePart[j].freeStart, freePart[j + 1].freeStart);
change(freePart[j].freeLength, freePart[j + 1].freeLength);





/*找出当前i号请求进行能放得下的区号,并返回区号*/
int findInsertPartNo(int i)
//找到当前i能放得下的区号
int partNo = -1;
for (int j = 0; j < freeNum; j++)
if (request[i].reqLength <= freePart[j].freeLength)
partNo = freePart[j].freePartNo;
//cout << "找到区号:" << partNo << endl;
return partNo;


return -1;


/*最佳使用算法*/
void zuijia()
cout << "当前请求表信息如下:" << endl;
cout << "顺序\\t进程名\\t请求长度" << endl;
for (int i = 0; i < reqNum; i++)
cout << i + 1 << "\\t" << request[i].reqProcessNo << "\\t" << request[i].reqLength << endl;


InitZuijia();
int i=0;
for (i; i < reqNum; i++)

//找到当前i能放得下的区号
int partNo = -1;
partNo = findInsertPartNo(i);

if (i==0 && partNo == -1)
cout << "该策略下空间不足,未做任何分配!" << endl;
return;

else if (partNo == -1)
cout << "仅分配部分进程!剩余未分配进程如下:" << endl;
cout << "\\t进程名\\t请求长度" << endl;
for (int j = 0; j < reqNum; j++)
if (request[j].reqed == 0)
cout << "\\t" << request[j].reqProcessNo << "\\t" << request[j].reqLength << endl;


break;


//寻找插入点并放入
for (p = head; p != NULL; p = p->next)
if (p->partNo == partNo)
//cout << "找到对应的插入点" << endl;
insert(p,i);


//初始化链表、空闲表
InitZuijia();

if (i == reqNum)
cout << "请求表中的进程全部分配完毕!" << endl;
printDongtai();

//对请求表数据更新(删除)
refeshReq(i);


//最坏适应算法

/*对找出所有空闲区安装递减排序*/
void InitZuihuai()
findFreePart();
//按空闲分区大小递减排序
for (int i = 0; i < freeNum - 1; i++)
for (int j = 0; j < freeNum - i - 1; j++)
if (freePart[j].freeLength < freePart[j + 1].freeLength)
change(freePart[j].freePartNo, freePart[j + 1].freePartNo);
change(freePart[j].freeStart, freePart[j + 1].freeStart);
change(freePart[j].freeLength, freePart[j + 1].freeLength);





/*最坏适应算法*/
void zuihuai()
cout << "当前请求表信息如下:" << endl;
cout << "顺序\\t进程名\\t请求长度" << endl;
for (int i = 0; i < reqNum; i++)
cout << i + 1 << "\\t" << request[i].reqProcessNo << "\\t" << request[i].reqLength << endl;


InitZuihuai();
int i = 0;
for (i; i < reqNum; i++)

//找到当前i能放得下的区号
int partNo = -1;
partNo = findInsertPartNo(i);

if (i == 0 && partNo == -1)
cout << "该策略下空间不足,未做任何分配!" << endl;
return;

else if (partNo == -1)
cout << "仅分配部分进程!剩余未分配进程如下:" << endl;
cout << "\\t进程名\\t请求长度" << endl;
for (int j = 0; j < reqNum; j++)
if (request[j].reqed == 0)
cout << "\\t" << request[j].reqProcessNo << "\\t" << request[j].reqLength << endl;


break;


//寻找插入点并放入
for (p = head; p != NULL; p = p->next)
if (p->partNo == partNo)
insert(p, i);


//初始化链表、空闲表
InitZuihuai();

if (i == reqNum)
cout << "请求表中的进程全部分配完毕!" << endl;
printDongtai();

//对请求表数据更新(删除)
refeshReq(i);


//分配一个分区
void feipeiFenqu()
if (reqNum == 0)
cout << "当前没有未分配空间的进程!" << endl << endl;
return;

cout << "  1、最先适应算法" << endl;
cout << "  2、最佳适应算法" << endl;
cout << "  3、最坏适应算法" << endl;
cout << "  请选择分配策略:";
int choose;
cin >> choose;


switch (choose)
case 1:
zuixian();
break;

case 2:
zuijia();
break;

case 3:
zuihuai();
break;

default:
break;



void printDongtai()
cout << "区号\\t首址\\t长度\\t尾址\\t状态\\t占用进程编号" << endl;
int i = 0;
for (p = head; p != NULL; p = p->next)
cout << " " << p->partNo << "\\t" << p->start << "\\t" << p->length << "\\t" << p->end << "\\t";
if (p->status == 1)
cout << "占用\\t" << p->processNo << endl;
else
cout << "空闲" << endl;
i++;

cout << endl;


//释放一个分区
void shifangFenqu()
cout << "请输入欲释放内存的区号:";
int freePart;
cin >> freePart;
p = head;
for (int i = 0; i <= freePart; i++)
if(i!=freePart)
p = p->next;

if (p->status == 1)
p->status = 0;
p->processNo = "";
cout << freePart<<"号分区释放成功!" << endl;

//分区合并·碎片整理
for (p = head; 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;

q = p->next;
p->next = q->next;
delete q;

else
p = p->next;


else
p = p->next;

//碎片整理结束

InitpartNo();

else
cout << "当前分区空闲,无需释放!" << endl;

printDongtai();
cout << endl;


//添加进程到请求队列中
void addProcess()
cout << "请输入进程编号和请求长度:";
//如果进程编号不存在,则继续执行
if (1)
cin >> request[reqNum].reqProcessNo >> request[reqNum].reqLength;
reqNum++;
cout<<"添加成功!"<<endl;

cout << endl;


int main()
InitDongtai();
while (1)
cout << "********菜 单********" << endl;
cout << " 1、显示分区状态" << endl;
cout << " 2、释放分区" << endl;
cout << " 3、分配分区" << endl;
cout << " 4、添加进程(作业)" << endl;

cout << " 请输入选项:";
int choice;
cin >> choice;

switch (choice)
case 1:
printDongtai();
break;

case 2:
shifangFenqu();
break;

case 3:
feipeiFenqu();
break;

case 4:
addProcess();
break;

default:
break;


return 0;


以上是关于操作系统课内实践:内存管理的主要内容,如果未能解决你的问题,请参考以下文章

Android最佳性能实践——合理管理内存

(转)Android进程管理详解

Linux 学习总结(二十三)系统管理技巧2

golang内存扩容

如何查看linux系统中空闲内存/物理内存使用/剩余内存

操作系统内存管理之 内部碎片vs外部碎片