一、实验题目: 模拟动态分区首次适应分配和回收算法
二、实验目的: 通过本实验,可加深理解动态分区分配、回收程序的功能和具体实现,特别是对回收分区的合并的理解。
三、实验环境:
1、硬件:PC机及其兼容机。
2、软件:Windows OS,MS—DOS OS,Turbo C 或 C++、VC++等。
四、实验内容:
1、 设计动态分区首次适应分配、回收算法。
2、 设计“空闲分区表”,格式为:
4、设计显示程序,将“未分配区说明表”和“已分配区说明表”的内容,显示在屏幕上。
5、 初始分配从一个空闲区分配起,回收时要合并空区。
五、运行示例:
六、算法流程图:
七、程序清单:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<windows.h>
#define N 5
#define MINSIZE 10//最大碎片大小
typedef struct EMP{
int no;//分区编号
int iadd;//起始地址
int length;//长度
int status;//状态 1-占有,0未占有
}EMP;
typedef struct USE{
int no;//分区编号
int iadd;//起始地址
int length;//长度
int status;//状态 1-占有,0未占有
char job[10];//作业名
}USE;
void menu(){
printf("---------OS实验三:模拟动态分区首次适应分配和回收算法---------\n");
printf("---------------------------系统菜单---------------------------\n");
printf("----------------------------1.分配----------------------------\n");
printf("----------------------------2.回收----------------------------\n");
printf("----------------------------3.显示----------------------------\n");
printf("----------------------------0.退出----------------------------\n");
printf("---------------------请输入您需要的功能(0-3)------------------\n");
printf("--------------------------------------------------------------\n");
printf("各功能简要说明:\n");
printf("分配功能:选择该功能后,首先输入需要分配空间的作业名及所需空间的大小。然后,按照首次适用算法从空闲分区表中找到一个合适的分区,若找到,则划分相应的空闲分区给该作业(修改“未分配区说明表”和“已分配区说明表”中的内容);若没有找到,需要给出相应的提示信息。\n");
printf("回收算法:选择该功能后,首先输入需要回收的作业的名称,然后,系统按照该名称从“已分配区说明表”中找到该作业对应的表项,若找到,则回收该分区(修改“未分配区说明表”和“已分配区说明表”中的内容),要注意空闲分区的合并与空闲分区表需要按地址有序调整;若没有找到,则给出相应的提示信息。\n");
printf("显示分区表:将两个分区表的内容显示在屏幕上,以便随时查看程序的运行情况。\n");
}
void allocation(EMP e[],USE u[]){//分配内存
int i,j,k;
int flag;
char tempname[10]={'\0'};
int templength;
system("cls");
printf("-------内存分配-------\n");
while(flag){
printf("请输入作业名:");
scanf("%s",tempname);
getchar();
printf("请输入请求的内存空间:");
scanf("%d",&templength);
getchar();
for(i=0;i<N;i++)
if(e[i].status==1 && e[i].length>=templength)
break;
if(i==N)
printf("wait a moment!");
else{
k=e[i].length-templength;
if(k<=MINSIZE)//该空间完全分配给进程
e[i].status=0;
else{//空闲区有剩余,因此表中仍保留该分区
for(j=0;j<N;j++)
if(u[j].status==0)
break;
u[j].iadd=e[i].iadd;
u[j].length=templength;
u[j].status=1;
strcpy(u[j].job,tempname);//必须先修改分区使用表
e[i].length-=templength;
e[i].iadd+=templength;//修改空闲分区表
}
printf("分配成功!\n");
}
printf("是否继续运行作业:1-是 0-否");
scanf("%d",&flag);
}
}
void recycle(EMP e[],USE u[]){//回收内存
int i,j,k,flag=1;
EMP emp;//临时变量,排序是使用
char tempname[10];
system("cls");
printf("-------内存回收-------\n");
while(flag){
k=0;
printf("请输入回收作业名:");
scanf("%s",tempname);
while( strcmp(u[k].job,tempname) && k<N || u[k].status==0 )
k++;
if(k==N)
printf("未找到该作业!");
else{//找到该作业
u[k].status=0;
for(i=0;i<N;i++)
if( (e[i].iadd+u[k].length)==u[k].iadd && e[i].status==1 )
for(j=0;j<N;j++)
if( e[j].iadd==(u[k].iadd+u[k].length) && e[j].status==1){//上下相邻空闲分区
e[i].length+=e[j].length+u[k].length;
e[j].status=0;
//printf("1");
break;
}
else//只有上相邻的空闲分区
e[i].length+=u[k].length;
if(i==N){//无上相邻
for(j=0;j<N;j++)
if( e[j].iadd==(u[k].iadd+u[k].length) && e[j].status==1){//下相邻空闲分区
e[j].length+=+u[k].length;
e[j].iadd=u[k].iadd;
//printf("2");
break;
}
if(j==N){//上下不相邻
for(j=0;j<N;j++)
if(e[j].status==0) break;
e[j].iadd=u[k].iadd;
e[j].length=u[k].length;
e[j].status=1;
//printf("3");
}
}
printf("回收成功!");
}
for(i=0;i<N-1;i++)//按首次适应算法调整空闲分区表的顺序
for(j=i+1;j<N;j++)
if(e[j].iadd<e[i].iadd){
emp=e[j];
e[j]=e[i];
e[i]=emp;
}
printf("是否继续回收作业:1-是 0-否");
scanf("%d",&flag);
}
}
void show(EMP e[],USE u[]){//显示空闲分区表和分区使用表
int i,d;
system("cls");
printf("分区编号----起始地址------长 度-------状 态(空闲分区表)\n");//显示空闲分区表
for(i=0,d=0;i<N;i++){
if(e[i].status==1)
printf("%d\t\t%d\t %d\t\t%d\n",++d,e[i].iadd,e[i].length,e[i].status);
}
printf("\n分区编号----起始地址------长 度-------状 态----作业名(使用分区表)\n");//显示分区使用表
for(i=0,d=0;i<N;i++){
if(u[i].status==1)
printf("%d\t\t%d\t %d\t\t%d\t%s\n",++d,u[i].iadd,u[i].length,u[i].status,u[i].job);
}
printf("显示完毕!\n");
system("pause");
}
void main(){//主函数
int i,flag=1;
int select;
struct EMP emp[N],*e=emp;
struct USE use[N],*u=use;
e[0].iadd=400;//初始化空闲分区表和分区使用表
e[0].length=2160;
e[0].status=1;
u[0].status=0;
for(i=1;i<N;i++){
emp[i].status=0;
use[i].status=0;
}
while(flag){
system("cls");
menu();
scanf("%d",&select);
switch(select){
case 0:flag=0;break;
case 1:allocation(e,u);break;//分配内存
case 2:recycle(e,u);break;//回收内存
case 3:show(e,u);break;//显示表
default:printf("输入错误,请重新输入!");break;
}
}
}
八、程序中使用的数据结构及符号说明:
#define N 5
#define MINSIZE 10//最大碎片大小
typedef struct EMP{
int no;//分区编号
int iadd;//起始地址
int length;//长度
int status;//状态 1-占有,0未占有
}EMP;
typedef struct USE{
int no;//分区编号
int iadd;//起始地址
int length;//长度
int status;//状态 1-占有,0未占有
char job[10];//作业名
}USE;
int select;
struct EMP emp[N],*e=emp;
struct USE use[N],*u=use;
九、调试程序时出现问题说明及解决的方法:
- 由于忘却了c语言结构体数组函数调用的用法,又复习了相关知识
解决方法:
struct EMP emp[N],*e=emp;
struct USE use[N],*u=use; - 为作业分配内存空间时,分配后显示总是出错
解决方法:分配内存后在修改分区使用表和空闲分区表时,一定要先修改分区使用表,再修改空闲分区表,顺序千万不能错。 - 回收内存函数中,在查找u[k]空表目时,一定一定要加上u[k].status==0,不然会重复回收导致错误。
- 在调试运行结果时,多次遇到运行中断的问题
解决方法:再多处设置printf(“1”);以此找出断点在哪,判断出哪里程序有问题。 - 每次为作业回收空间后都需要按首次适应算法调整空闲分区表的顺序。