操作系统实验——主存分配与释放(C语言)

目录

实验要求

代码实现

运行结果

代码解析


实验要求

1、模拟操作系统的主存分配,运用可变分区的存储管理算法设计主存分配和回收程序,并不实际启动装入作业。

2、采用最先适应法。

3、当一个新作业要求装入主存时,必须查空闲区表,从中找出一个足够大的空闲区。若找到的空闲区大于作业需要量,这是应把它分成二部分,一部分为占用区,加一部分又成为一个空闲区。

4、当一个作业撤离时,归还的区域如果与其他空闲区相邻,则应合并成一个较大的空闲区,登在空闲区表中。

5、运行所设计的程序,输出有关数据结构表项的变化和内存的当前状态。 

代码实现

#include 
#define CAP 1024    //初始化内存容量 
#define SYSCAP 100  //系统所占地址,从低位开始 
#define N 1000		//进程最大个数 //作业分区 
struct USED{int id,sp,ep,longsize;
}a[N];//空闲分区 
struct FREE{int id,sp,ep,longsize;
}b[N];//anum为作业分区块数,bnum为空闲分区块数。初始时作业分区0块,空闲分区有1块
int anum=0,bnum=1;        
void Init()              //初始化函数,程序开始时只有一个空闲分区 
{b[0].id=0;b[0].sp=SYSCAP;b[0].ep=CAP;b[0].longsize=b[0].ep-b[0].sp;printf("\n\n--------------最先适应算法--------------\n"); printf("\n内存总量为:%dk\n",CAP); printf("系统占用容量为:%dk\n",SYSCAP);printf("---------------------------------------------\n"); printf("空闲分区    起始地址    结束地址    长度\n");printf("   %d          %d         %d       %d\n",b[0].id,b[0].sp,b[0].ep,b[0].longsize);printf("---------------------------------------------\n"); 
}
void Print(int anum,int bnum)      //格式化输出作业分区和空闲分区表 
{int i,j;printf("-----------------作业分区表---------------------\n"); printf("作业分区    起始地址    结束地址    长度\n");for(i=0;i=size)     //找到第一个能放下进程的空闲分区 {a[anum].id=anum;			//空闲区id a[anum].sp=b[i].sp;			//作业内存起始地址等于空闲分区起始地址 a[anum].ep=a[anum].sp+size; //作业的结束地址等于起始地址+作业长度 b[i].sp=b[i].sp+size;		//空闲分区起始地址应向后移动size a[anum].longsize=size;		//更新作业地址长度到结构体数组中 b[i].longsize=b[i].ep-b[i].sp;//更新空闲分区地址长度 anum++;						//作业数+1 break;						//一次只放入一个作业,结束查找 }}Print(anum,bnum);                   //打印结果 
}void Merge()	//合并空闲分区,查找结束地址和开始地址重合的地址进行合并 
{int i,j;if(bnum>=1)   //当空闲分区大于等于两个时,才需要检查是否存在可合并的区间 {for(i=0;i

运行结果

 代码解析

将内存总量,系统内存进行宏定义(有需要的直接修改宏定义的数据即可)

定义两个结构体数组,分别用于存放和空闲分区的状态数据

anum和bnum为全局变量,分别代表作业分区和空闲分区的数量 

#include 
#define CAP 1024    //初始化内存容量 
#define SYSCAP 100  //系统所占地址,从低位开始 
#define N 1000		//进程最大个数 
//作业分区 
struct USED{int id,sp,ep,longsize;
}a[N];
//空闲分区 
struct FREE{int id,sp,ep,longsize;
}b[N];
int anum=0,bnum=1;

  

 初始化函数,在算法程序未开始处理前打印初始数据。这里数组下标从0开始

void Init()              //初始化函数,程序开始时只有一个空闲分区 
{b[0].id=0;b[0].sp=SYSCAP;b[0].ep=CAP;b[0].longsize=b[0].ep-b[0].sp;printf("\n\n--------------最先适应算法--------------\n"); printf("\n内存总量为:%dk\n",CAP); printf("系统占用容量为:%dk\n",SYSCAP);printf("---------------------------------------------\n"); printf("空闲分区    起始地址    结束地址    长度\n");printf("   %d          %d         %d       %d\n",b[0].id,b[0].sp,b[0].ep,b[0].longsize);printf("---------------------------------------------\n"); 
}

打印结果,按顺序打印对应的结构体数据

void Print(int anum,int bnum)      //格式化输出作业分区和空闲分区表 
{int i,j;printf("-----------------作业分区表---------------------\n"); printf("作业分区    起始地址    结束地址    长度\n");for(i=0;i

 核心算法:将作业装入内存(具体实现方法全都写入注释里了,如果还有有不懂的可以私信我)

void Put()                   //进程装入作业 
{int size;printf("请输入作业%d的大小\n",anum);scanf("%d",&size);int i;for(i=0;i=size)     //找到第一个能放下进程的空闲分区 {a[anum].id=anum;			//空闲区id a[anum].sp=b[i].sp;			//作业内存起始地址等于空闲分区起始地址 a[anum].ep=a[anum].sp+size; //作业的结束地址等于起始地址+作业长度 b[i].sp=b[i].sp+size;		//空闲分区起始地址应向后移动size a[anum].longsize=size;		//更新作业地址长度到结构体数组中 b[i].longsize=b[i].ep-b[i].sp;//更新空闲分区地址长度 anum++;						//作业数+1 break;						//一次只放入一个作业,结束查找 }}Print(anum,bnum);                   //打印结果 
}

 核心算法:将作业回收,作业所占据的内存重新收回变为空闲区

 这里说一下代码中写的回收作业时为什么要分两种情况

情况1:

在作业回收时,进入空闲分区能直接和空闲分区直接合并,不需要增加新的空闲分区块(如下图)

 回收合并后:

情况2:

在作业回收时,进入空闲分区时不能直接和空闲分区直接合并,需要增加新的空闲分区块(如下图,黄色块为待回收的作业分区)

回收合并后:

void Remove()//回收作业 
{int i,j,flag=1;//flag是标志位 printf("请输入需要回收的作业:\n");scanf("%d",&i);//回收作业存在下面两种情况 for(j=0;j

排序算法,每次进行回收后按地址从大到小进行重新排序(这一步处理必须有)

作业回收时是任意的,如果先回收了高地址块不排序,在下一次检索空闲分区时会先把高地址分出去,显然这是不符合最佳适应算法的定义的

void Sort(int anum,int bnum)//简单排序函数,将空闲区间按起始地址递增的顺序排序 
{int i,j,min;for(i=0;i

 合并函数,进行检查再合并处理,这里其实是在处理前面两种情况之后出现的第三种情况

 

回收合并后: 

void Merge()	//合并空闲分区,查找结束地址和开始地址重合的地址进行合并 
{int i,j;if(bnum>=1)   //当空闲分区大于等于两个时,才需要检查是否存在可合并的区间 {for(i=0;i

主函数。通过用户输入来调用对应处理函数

int main()
{int input;//input 代表程序运行状态Init();//初始化,输出 while(1)//写一个死循环 {printf("装入作业:1  回收作业:0  其他输入结束程序\n");scanf("%d",&input);if(input==1){Put();}else if(input==0){Remove();}else break;//任意数字退出循环,程序结束 }return 0;
}

感谢阅读~各位有什么好的建议评论或者私信我都可以~有没看懂的地方也可以私信我~

觉得有用的话点个赞再走吧~


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章