基本信息
源码名称:c++ 实验:可变分区管理
源码大小:0.11M
文件格式:.zip
开发语言:C/C++
更新时间:2018-12-21
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
模拟主存储器空间的分配和回收。
模拟主存储器空间的分配和回收。
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 128 //系统分配给用户的最大内存
typedef struct MCB{//内存控制块
int add; //分区起始地址
int sta; //分区状态,0为可用
int size; //分区大小
int jno; //分区装入作业号,作业号从1开始
struct MCB* next; //链连指针
}MCB;
MCB *free_table,*ft; //可用分区的头指针,尾指针
MCB *used_table,*ut; //已分配分区的头指针,尾指针
void initFree_table()//初始化可用区链表,初始大小为整个用户分区
{
if(!(free_table=(MCB*)malloc(sizeof(struct MCB))))
exit(1);
free_table->add = 0;
free_table->size = MAX_SIZE;
free_table->sta = 0;
free_table->jno = 0;
free_table->next = NULL;
ft=free_table;
}
void initUsed_table()//初始化已分配分区链表
{
if(!(used_table=(MCB*)malloc(sizeof(struct MCB))))
exit(1);
used_table->add = 0;
used_table->size = 0;
used_table->sta = 1;
used_table->jno = 0;
used_table->next = NULL;
ut=used_table;
}
void add_ut(MCB *pf,int size,int jno)
{
//修改已分配链表
if(used_table->next == NULL && used_table->size == 0)
{//已用分区表的第一块
used_table->add = pf->add;
used_table->size = size;
used_table->jno = jno;
}else{//将新增分区加到已分配链表末尾
//pt为临时MCB
MCB *pt;
if(!(pt=(MCB*)malloc(sizeof(struct MCB))))
exit(1);
pt->size = size;
pt->add = pf->add;
pt->jno = jno;
pt->sta = 1;
pt->next = NULL;
ut->next = pt;
ut = ut->next;
}
}
void allot(int jno,int size)//首次适应法为作业分配存储空间
{
if(jno <= 0 ) /*|| jno有重复*/
{
printf("输入作业号有误,请重新输入!\n");
return;
}
if(size > MAX_SIZE)
{
printf("作业太大,无法分配!\n");
return;
}
if(size <= 0)
{
printf("作业大小不合法!\n");
}
//查空白分区链表
MCB *pf = free_table;
MCB *p=pf;
while(pf != NULL && pf->size < size)
{
p = pf;
pf = pf->next;
}
if(pf == NULL)
{
printf("未找到可用分区!\n");
return;
}
if(pf->size == size){
//把该分区从可用区链表中删除
if(pf == free_table)
{/*删除的是头结点*/
free_table->sta = 1;
if(free_table->next != NULL)
{//存在后续结点,则头指针后移
free_table = free_table->next;
}else{//只有一个结点,则置空可用区
free_table->size = 0;
}
}else{
pf->sta = 1;
p->next = pf->next;
pf->next = NULL;
}
//将新增分区pf加到已分配链表
add_ut(pf,size,jno);
}else if(pf->size > size){
//把空白分区一分为二
//将新增分区pf加到已分配链表
add_ut(pf,size,jno);
//修改空闲分区链表
pf->add = pf->add size;
pf->size -= size;
pf->jno = 0;
}
printf("作业空间已成功分配...\n\n");
return;//正常分配
}
void reclaim(int jno)//回收内存空间
{
//从used_table中找到jno
MCB *pu = used_table;
MCB *p = pu;//指向要回收块,即回收作业的前一个项
while(pu && pu->jno != jno)
{
p = pu;
pu = pu->next;
}
if(pu == NULL)
{
printf("没有找到作业编号为%d的作业!\n\n",jno);
return;
}
int size = pu->size;
//删除used_table中的jno块,即pu
if(pu == used_table) /*删除的是头结点*/
{
if(used_table->next != NULL)
{
used_table = used_table->next;
}else{
used_table->size = 0;
}
}else{
p->next = pu->next;
}
//把jno块pu插入free_table
if(free_table->next == NULL && free_table->size == 0)
{//可用区为空,则创建新的可用区
free_table->size = size;
free_table->add = pu->add;
free_table->sta = 0;
free_table->next = NULL;
}else{/*查到应插入的位置,分两大种情况:在头结点之前,之后*/
MCB *pf=free_table;//下一个位置,或下邻区
MCB *q=pf; //q为要插入的位置,或上邻区
/*插入位置在可用区头结点之前*/
if(pu->add size < free_table->add)
{
MCB *tmp;
if(!(tmp=(MCB*)malloc(sizeof(struct MCB))))
exit(1);
tmp->next = free_table;
tmp->jno = 0;
tmp->add = pu->add;
tmp->size = pu->size;
tmp->sta = 0;
free_table = tmp;
}else if(pu->add size == free_table->add){
/*插入位置和可用区头结点下邻*/
free_table->add -= size;
free_table->size = size;
}else{/*插入位置在可用区头结点之后*/
//查找位置
while(pf->next != NULL && pf->add pf->size <= pu->add)
{
q = pf;
pf = pf->next;
}
if(q->add q->size == pu->add)/*有与归还区上邻的空闲区*/
{
//归还长度 下邻区长度
q->size = q->size size;
if(pf->add == pu->add size)/*有与归还区下邻的空闲区*/
{
//删除下邻链接点
q->next = pf->next;
//把上邻空闲节点的长度增加归还块长度
q->size = q->size pf->size;
free(pf);
}
}else{
q->next = pu;
if(pf->add == pu->add size)/*有与归还区下邻的空闲区*/
{
//把上邻空闲节点的长度增加归还块长度
pu->size = size pf->size;
pu->next = pf->next;
free(pf);
}else{//把归还块直接插入未分配链表中
pu->next = pf;
pu->jno = 0;
}
}
}
}
printf("成功回收作业分区!\n");
}
void displayUt(MCB *pMCB)//显示已使用作业分区表
{
if(pMCB == NULL || pMCB->size == 0)
{
printf("\t当前内存中没有任何作业!\n\n");
return;
}
MCB *p=pMCB;
printf("\t作业编号\t起始地址\t结束地址\t分区大小\n");
while( p != NULL)
{
printf("\t%d\t\t%d\t\t%d\t\t%d\n",p->jno,p->add,p->add p->size,p->size);
p = p->next;
}
printf("\n");
}
void displayFt(MCB *pMCB)//显示空闲主存分区表
{
if(pMCB->size == 0)
{
printf("\t当前主存没有可用分区!\n\n");
return;
}
MCB *p=pMCB;
printf("\t起始地址\t结束地址\t分区大小\n");
while( p != NULL)
{
printf("\t%d\t\t%d\t\t%d\n",p->add,p->add p->size,p->size);
p = p->next;
}
printf("\n");
}
int main()
{//菜单选择
int select=0,jno=0,size=0;
initFree_table();
initUsed_table();
printf("\t\t\t可变分区管理-首次适应算法实验\n");
printf("\t\t\t\t--Powered by ZhangHua\n");
printf("\t本程序为便于计算,0号分区不使用,默认分区编号为1~128\n\n");
do{
printf("\t\t\t请选择操作命令:\n");
printf("\t\t\t1:分配作业存储空间\n");
printf("\t\t\t2:回收作业存储空间\n");
printf("\t\t\t3:显示可用主存信息\n");
printf("\t\t\t4:显示已用主存信息\n");
printf("\t\t\t0:退出\n\n");
scanf("%d",&select);
switch(select)
{
case 0:
exit(0);
break;
case 1:
printf("请输入作业编号(从1开始,请勿重复输入已存在的作业编号!):");
scanf("%d",&jno);
printf("请输入作业%d所需内存大小:",jno);
scanf("%d",&size);
allot(jno,size);
break;
case 2:
printf("请输入要回收的作业空间编号:");
scanf("%d",&jno);
reclaim(jno);
break;
case 3:
printf("\t\t\t可用分区情况如下:\n\n");
displayFt(free_table);
break;
case 4:
printf("\t\t\t已用分区情况如下:\n\n");
displayUt(used_table);
break;
default:
printf("输入字符无效,请请重新输入!\n");
}
}while(select);
return 0;
}