吉林大学操作系统上机实验三(存储管理算法NF实现)

操作系统上机随笔《实验三》

老规矩,上文是本次实验的基础内容,本文实现加分项:除First Fit存储分配算法外,其他算法

NF算法的实现 

NF算法(下次适应算法,Next Fit)介绍:


思想:

自上次分配空闲区域的下一个位置开始,选取第一个可满足的空闲区域

实现:

设置一个循环查找指针,开始时指向表头,每次分配从该指针处开始查找(若查到表尾则将指针置到表头)第一个遇到的可满足的区域,分配后将指针调整为所分配区域的下一个区域处。

优点:

可以减少查找空闲区域所花费的时间开销,并使空闲区域分布更均匀。

缺点:

可能分割大空闲区

代码:

#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];  //存储资源表
struct map* np = NULL;
//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);
}

//NF存储分配函数
int NF_malloc(struct map* mp, int size)
{
    register int a;
    register struct map* bp;
    if (!np || np->m_size == 0) {
        np = mp;
    }
    bp = np;
    do {
        if (bp->m_size >= size)
        {
            a = bp->m_addr;
            np = bp + 1;
            bp->m_addr += size;
            if ((bp->m_size -= size) == 0) {
                np--;
                do
                {
                    bp++;
                    (bp - 1)->m_addr = bp->m_addr;
                } while ((bp - 1)->m_size = bp->m_size);
            }

            return(a);
        }
        bp++;
        if (bp->m_size == 0) bp = mp;
    } while (bp != np);
    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;
                if (np && bp == np) np--;
            }
        }
    }

    else
    {
        if (a + size == bp->m_addr && bp->m_size)
        {   //与后合并
            bp->m_addr -= size;
            bp->m_size += size;
        }
        else if (size) {
            int  flag = 0;

            do
            {   //无合并,插入新空闲区域,后面所有向后移动
                t = bp->m_addr;
                bp->m_addr = a;
                a = t;
                t = bp->m_size;
                bp->m_size = size;
                if (bp == np) flag = 1;
                bp++;
            } while (size = t);
            if (np && flag) np++;
        }
            
    }
}
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");
}

int main()
{
    int a, s;
    char c;
    int i;
    init();
    printf("please input, b for BF, w for WF,n for NF:");
    scanf("%c", &c);
    getchar();
    do
    {
        show_map(); //显示存储资源表
        if (np) printf("np: %d\n", np->m_addr);
        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 if (c == 'w')  //WF
                a = WF_malloc(map, s);
            else
                a = NF_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);
}

具体实现: 

struct map* np = NULL;

保存一个全局变量指针 np ,即循环查找指针,未使用时指空。

//NF存储分配函数
int NF_malloc(struct map* mp, int size)
{
    register int a;
    register struct map* bp;
    if (!np || np->m_size == 0) {
        np = mp;
    }
    bp = np;
    do {
        if (bp->m_size >= size)
        {
            a = bp->m_addr;
            np = bp + 1;
            bp->m_addr += size;
            if ((bp->m_size -= size) == 0) {
                np--;
                do
                {
                    bp++;
                    (bp - 1)->m_addr = bp->m_addr;
                } while ((bp - 1)->m_size = bp->m_size);
            }

            return(a);
        }
        bp++;
        if (bp->m_size == 0) bp = mp;
    } while (bp != np);
    return(-1);
}

1.进入 NF 后,先判断 np 是否指空或指向表位,如果是,将其重新指向表头。

2.从 np 开始,向后查找第一个足够大的空闲块,如果遍历到表尾,重新指向表头,直到再次遍历到 np 的话,返回-1。如果找到,更新该块首地址和大小,以反映内存分配,并将 np 指向下一个块。如果分配后块的大小为0,移除此块,后面的块依次向前移动,np 也向前移动。返回分配首地址a。

mfree函数的适应性调整:

//存储释放函数
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;
                if (np && bp == np) np--;
            }
        }
    }

    else
    {
        if (a + size == bp->m_addr && bp->m_size)
        {   //与后合并
            bp->m_addr -= size;
            bp->m_size += size;
        }
        else if (size) {
            int  flag = 0;

            do
            {   //无合并,插入新空闲区域,后面所有向后移动
                t = bp->m_addr;
                bp->m_addr = a;
                a = t;
                t = bp->m_size;
                bp->m_size = size;
                if (bp == np) flag = 1;
                bp++;
            } while (size = t);
            if (np && flag) np++;
        }
            
    }
}

问题:

存储释放时,若前后都合并或都不合并时,后续块需要移动。此时,若 np 所指向的块被移动,需更新 np 

具体修改:

1.若前后都合并,后续块向前移动过程中遍历到 np 所指的块,更新 np--

2.若前后都不合并,后续块向后移动过程中,若遍历到 np 所指的块,记录,都遍历完成后,更新 np++。

运行结果:

(为了直观展示 np 指针的效果,在主函数中,show_map后,输出np->m_addr。)

分析: 

由图一可以看出,申请70大小的块后,np 指向表位。且释放存储后,仍能正确指向表位;

由图二可以看出,再次申请10大小的块时,由于 np 指向表位,再次从头开始遍历。(不是BF算法);

申请5大小的块后,再次申请10大小的块,都能从正确的块中分配空间。(不是WF算法)。

由图三可以看出,当遍历到表尾时,回回到表头继续遍历。 

结尾 

别忘了在主函数中正确适配NF算法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值