前言
一天一个实验,今天是第三天,接着开赶进度
1,实验目的
理解动态异长存储分区资源管理,掌握所需数据结构和管理程序,了解各种存储分配算法的优点和缺点。
2,实验内容
- 分析UNIX最先适应(FF)存储分配算法,即map数据结构、存储分配函数malloc()和存储释放函数mfree(),找出与算法有关的成分。
- 修改上述与算法有关的成分,使其分别体现BF分配原则和WF分配原则。
3,实验准备
这个实验的内容也很好理解,知识点的内容就在教材的P108页,在使用链表的存储管理这一小节里面有关于BF和WF的简要介绍,如图:
我又找了一个帖子简要的介绍了这两个算法:
(20条消息) 实例分析首次适应算法、最佳适应算法、最差适应算法_焕听的博客-CSDN博客_循环首次适应算法例题讲解
(实验设计只要求我们设计出BF和WF的分配算法,回收算法先不考虑)
4,实验设计
- 按内容要求编写最佳适应和最坏适应存储分配算法。
- 编写测试程序,对存储分配表进行初始化。然后对用户输入的请求和释放,按算法动态更新存储分配表,并将每次更新之后的存储分配表在屏幕上显示出来。
实验代码
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#define MAPSIZE 100
struct map //存储资源表结构
{
int m_addr;
int m_size;
};
struct map map[MAPSIZE]; //存储资源表
//BF存储分配函数
int BF_malloc(struct map *mp,int size)
{
register int a,s;
register struct map *bp,*bpp;
for(bp = mp; bp->m_size; bp++)
{
if (bp->m_size >= size)
{
a = bp->m_addr;
s = bp->m_size;
for(bpp = bp; bpp->m_size; bpp++)
{ //最佳适应
if(bpp->m_size >= size && bpp->m_size < s)
{
a = bpp->m_addr;
s = bpp->m_size;
bp = bpp;
}
}
bp->m_addr += size;
if ((bp->m_size -= size) == 0)
do
{
bp++;
(bp-1)->m_addr = bp->m_addr;
}
while((bp-1)->m_size = bp->m_size);
return(a);
}
}
return(-1);
}
//WF存储分配函数
int WF_malloc(struct map *mp,int size)
{
register int a,s;
register struct map *bp,*bpp;
for(bp = mp; bp->m_size; bp++)
{
if (bp->m_size >= size)
{
a = bp->m_addr;
s = bp->m_size;
for(bpp = bp; bpp->m_size; bpp++)
{ //最坏适应
if(bpp->m_size > s)
{
a = bpp->m_addr;
s = bpp->m_size;
bp = bpp;
}
}
bp->m_addr += size;
if ((bp->m_size -=size) == 0)
do
{
bp++;
(bp-1)->m_addr = bp->m_addr;
}
while((bp-1)->m_size = bp->m_size);
return(a);
}
}
return(-1);
}
//存储释放函数
void mfree(struct map *mp,int aa,int size)
{
register struct map *bp;
register int t;
register int a;
a = aa;
for(bp = mp; bp->m_addr<=a && bp->m_size != 0; bp++)
;
if(bp>mp && (bp-1)->m_addr+(bp-1)->m_size==a)
{ //与前合并
(bp-1)->m_size += size;
if (a+size == bp->m_addr)
{ //前后合并
(bp-1)->m_size += bp->m_size;
while (bp->m_size)
{
bp++;
(bp-1)->m_addr = bp->m_addr;
(bp-1)->m_size = bp->m_size;
}
}
}
else
{
if (a+size == bp->m_addr && bp->m_size)
{ //与后合并
bp->m_addr -= size;
bp->m_size += size;
}
else if (size)
do
{ //无合并
t = bp->m_addr;
bp->m_addr = a;
a = t;
t = bp->m_size;
bp->m_size = size;
bp++;
}
while (size = t);
}
}
void init()
{
struct map *bp;
int addr,size;
int i=0;
bp=map;
printf("Please input starting addr and total size:");
scanf("%d,%d",&addr,&size);
getchar();
bp->m_addr=addr;
bp->m_size=size;
(++bp)->m_size=0; //表尾
}
void show_map()
{
int i=0;
//system("clear"); //清屏
struct map *bp;
bp=map;
printf("\nCurrent memory map...\n");
printf("Address\t\tSize\n");
while(bp->m_size!=0)
{
printf("<%d\t\t%d>\n",bp->m_addr,bp->m_size);
bp++;
}
printf("\n");
}
main()
{
int a,s;
char c;
int i;
init();
printf("please input, b for BF, w for WF:");
scanf("%c",&c);
getchar();
do
{
show_map(); //显示存储资源表
printf("Please input,1 for request,2 for release,0 for exit:");
scanf("%d",&i);
getchar();
switch(i)
{
case 1:
printf("Please input size:");
scanf("%d", &s);
getchar();
if(c=='b') //BF
a=BF_malloc(map,s);
else //WF
a=WF_malloc(map,s);
if(a==-1)
printf("request can't be satisfied\n");
else
printf("alloc memory at address:%d,size:%d\n",a,s);
break;
case 2:
printf("Please input addr and size:");
scanf("%d,%d",&a,&s);
getchar();
mfree(map,a,s);
break;
case 0:
exit(0);
}
}
while(1);
}
修改:
1,!!!!!!!一定要把main函数里的int c,改为char c;如果不改的话无论程序运行过程中输入b还是w,执行的都是WF,这一点我调试了好久好久才发现的。
2,另外程序中但凡有scanf的地方后面都要加上getchar把缓冲区里的清空!!!这一点也很重要,否则你程序运行过程中该输入的地方没法输入的。
3,另外在main函数的do-while循环中把第一个printf删去,这个放的地方不对啊,而且这个scanf里面应该是%c。
输出结果:
BF:
说明:
可以看到当内存还有(20,55)和(70,100)这两个时,当我们再使用15的内存,使用BF算法会选择出合适内存中最小的一块,也就是(70,100),然后空闲内存还有(20,55)和(85,100),我们再使用10的内存,使用BF算法会选择出合适内存中最小的一块,也就是(85,100),然后空闲内存还有(20,55)和(95,100)。
WF:
说明:
可以看到当内存还有(20,55)和(70,100)这两个时,当我们再使用15的内存,使用WF算法会选择出合适内存中最大的一块,也就是(20,55),然后空闲内存还有(35,55)和(70,100),我们再使用10的内存,使用BF算法会选择出合适内存中最大的一块,也就是(70,100),然后空闲内存还有(35,55)和(85,100)。
分析实验结果:
函数功能:
BF_malloc函数:
调用该函数,在目前的map内,找到自己传入参数size的合适的并且范围最小的一块内存,并且占用该内存中size大小。
WF_malloc函数:
调用该函数,在目前的map内,找到自己传入参数size的合适的并且范围最大的一块内存,并且占用该内存中size大小。
mfree函数:
调用该函数,在目前的map内,释放出首地址为aa的,大小为size的一块内存,并且将该内存与已有的空闲内存进行合并。
init函数:
调用该函数是为了初始化map,获取该map大小。
show_map函数:
打印出目前map中空闲的内存块。
Main函数:
主函数,调用该函数,指明选择BF还是WF,并且在while循环中可以不断对内存进行操作。
函数之间调用关系:
在main函数中首先选择使用BF还是WF,然后调用init函数进行初始化map,然后在do-while循环中首先调用show_map函数打印出目前map空闲内存块,然后输入参数进行选择,输入1代表要占用内存,调用BF_malloc/WF_malloc选择合适的内存占用;输入2代表要释放内存,调用mfree函数释放内存;输入0代表结束程序。
关键语句功能说明:
for(bpp = bp; bpp->m_size; bpp++)
{ //最佳适应
if(bpp->m_size >= size && bpp->m_size < s)
{
a = bpp->m_addr;
s = bpp->m_size;
bp = bpp;
}
}
这一段在BF函数里面,主要作用是遍历目前的map,然后在其中找出范围大于size的,并且返回最小的一块内存的起点。
for(bpp = bp; bpp->m_size; bpp++)
{ //最坏适应
if(bpp->m_size > s)
{
a = bpp->m_addr;
s = bpp->m_size;
bp = bpp;
}
}
这一段在WF函数里面,主要作用是遍历目前的map,然后在其中找出范围大于size的,并且返回最大的一块内存的起点。
if(bp>mp && (bp-1)->m_addr+(bp-1)->m_size==a)
{ //与前合并
(bp-1)->m_size += size;
if (a+size == bp->m_addr)
{ //前后合并
(bp-1)->m_size += bp->m_size;
while (bp->m_size)
{
bp++;
(bp-1)->m_addr = bp->m_addr;
(bp-1)->m_size = bp->m_size;
}
}
}
else
{
if (a+size == bp->m_addr && bp->m_size)
{ //与后合并
bp->m_addr -= size;
bp->m_size += size;
}
else if (size)
do
{ //无合并
t = bp->m_addr;
bp->m_addr = a;
a = t;
t = bp->m_size;
bp->m_size = size;
bp++;
}
while (size = t);
}
这一段是在内存释放合并函数里的,主要功能是把函数传入的参数的一块内存放入map表内,并且将目前的map表进行一次遍历,如果有两块内存是相连的,则将其合并在一起。文章来源:https://www.toymoban.com/news/detail-495989.html
5,思考题
挖坑文章来源地址https://www.toymoban.com/news/detail-495989.html
参考
- (20条消息) 实例分析首次适应算法、最佳适应算法、最差适应算法_焕听的博客-CSDN博客_循环首次适应算法例题讲解
到了这里,关于操作系统上机随笔《实验三》的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!