可变分区存储管理(最先、下次、最佳、最差适配法)

可变分区存储管理,又称动态分区模式,是实存管理中连续存储的一种实现方式。
在分区的分配和回收时,根据不同的查找规则,有5种:

  • first fit,最先适应分配算法,按地址递增排序。
  • next fit,下次适应分配算法,在first fit基础上,从上次搜索结束为止开始搜索。
  • best fit,最佳适应分配算法,按空闲区长度从大到小排序。
  • worst fit,最坏适应分配算法,按空闲区长度递减排序。
  • quick fit,快速适应分配算法,将常用长度的空闲区有组织地存放。

这里以一份代码来演示最先适配法,下次适配法,最佳和最差适配法。源文件命名为variable_partition.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#define JOB_MAX 10
struct
{
    int address;
    int length;
    int id;
}used_table[JOB_MAX];

struct f_table
{
    int address;
    int length;
}free_table[JOB_MAX+1];

int free_num = 1;
int used_num = 0;
int comp_addr_increase(const void *p1, const void *p2)
{
    return ((struct f_table*)p1)->address - ((struct f_table*)p2)->address;
}
int comp_length_increase(const void *p1, const void *p2)
{
    return ((struct f_table*)p1)->length - ((struct f_table*)p2)->length;
}
int comp_length_decrease(const void *p1, const void *p2)
{
    return ((struct f_table*)p2)->length - ((struct f_table*)p1)->length;
}
int update_free_table()
{
    int i, j;
    if(free_num < 2)
        return 0;

    /* sort by address */
    qsort(free_table, free_num, sizeof free_table[0], comp_addr_increase);

    /* merge */
    for(i=0; i < free_num-1; i ++)
    {
        if(free_table[i].address + free_table[i].length == free_table[i+1].address)
        {
            free_table[i].length += free_table[i+1].length;
            for(j = i+1; j < free_num-1; j ++)
            {
                memcpy(&free_table[j], &free_table[j+1], sizeof free_table[0]);
            }
            free_num --;
            i --;
        }
    }

    /* sort by length if necessary */
#if defined( BEST_FIT )
    qsort(free_table, free_num, sizeof free_table[0], comp_length_increase);
#elif defined( WORST_FIT )
    qsort(free_table, free_num, sizeof free_table[0], comp_length_decrease);
#endif
    return 0;
}
int show()
{
    int i=0;

    printf(".-----------------------------------\n");
    printf("| free table:\n");
    if(free_num)
    {
        printf("|%10s %10s\n", "Address", "Length");
        for(i=0; i<free_num; i ++)
        {
            printf("|%10d %10d\n", free_table[i].address, free_table[i].length);
        }
    }
    else
    {
        printf("| no free table now!\n");
    }
    printf("|-----------------------------------\n");
    printf("| used table:\n");
    if(used_num)
    {   
        printf("|%10s %10s %5s\n", "Address", "Length","pid");
        for(i=0; i<used_num; i ++)
        {
            printf("|%10d %10d %5d\n", used_table[i].address, \
                    used_table[i].length, used_table[i].id);
        }
    }
    else
    {
        printf("|No job running now!\n");
    }
    printf(".-----------------------------------\n");

    return 0;
}   
/* return task id if no error
 * return -1 if no space for new task
 */
int allocate(int size)
{
    static int next_pid = 1;
    static int next_fit_pos = 0;
    int n;
    int i;

    if(used_num >= JOB_MAX || free_num < 1)
        return -1;
#if defined( NEXT_FIT )
    for(i = (next_fit_pos+1)%free_num, n = free_num; \
            n > 0; \
            i = (i+1)%free_num, n--)
#else
    for(i= 0; i<free_num; i ++)
#endif
    {
        if(size <= free_table[i].length)
        {
            used_table[used_num].id = next_pid ++;
            used_table[used_num].address = free_table[i].address;
            used_table[used_num].length = size;

            free_table[i].address += size;
            free_table[i].length -= size;
#if defined( NEXT_FIT )
            next_fit_pos = i;
#endif

            if(0 == free_table[i].length)
            {
                /* delete this free item */
                for(; i<free_num; i ++)
                {
                    memcpy(&free_table[i], &free_table[i+1], sizeof free_table[0]);
                }
                free_num --;
            }
            used_num ++;
            update_free_table();

            return next_pid-1;
        }
    }
    /* no enough size */
    return -1;
}
/*
 * return -1 if no such job
 * return 0 if no error
 */
int reclaim(int pid)
{
    int i;
    if(0 == used_num)
        return -1;
    for(i=0; i < used_num; i ++)
    {
        if(used_table[i].id == pid)
        {
            free_table[free_num].address = used_table[i].address;
            free_table[free_num].length = used_table[i].length;
            free_num ++;
            update_free_table();
            for(; i< used_num; i ++)
            {
                memcpy(&used_table[i], &used_table[i+1], sizeof used_table[0]);
            }
            used_num --;
            return 0;
        }
    }
    return -1;
}
int main()
{
    int input = 0;
    int pid;
    int size;
    int ret;

    free_table[0].address = 40000;
    free_table[0].length = 1000;

    show();
    while(1)
    {
        printf("0-quit  1-allocate  2-reclaim  input:");
        fflush(stdout);
        scanf("%d", &input);
        switch(input)
        {
        case 0:
            exit(1);
        case 1:
            printf("please input task size:");
            fflush(stdout);
            scanf("%d", &size);
            pid = allocate(size);
            if(pid > 0)
            {
                printf("job #%d is running\n", pid);
                show();
            }
            else
            {
                printf("job cannot run\n");
            }
            break;
        case 2:
            printf("please input the task id:");
            fflush(stdout);
            scanf("%d", &pid);
            ret = reclaim(pid);
            if(ret)
            {
                printf("no such job\n");
            }
            else
            {
                printf("job #%d reclaimed.\n", pid);
                show();
            }
            break;
        default:
            printf("no such choice\n");
        }
    }
    return 0;
}

对应的Makefile如下:

SOURCE_FILES = variable_partition.c
N=100

all:f n b w

f: $(SOURCE_FILES)
    gcc $(SOURCE_FILES) -o firstfit -DJOB_MAX=$N

n: $(SOURCE_FILES)
    gcc $(SOURCE_FILES) -o nextfit -DNEXT_FIT -DJOB_MAX=$N

b: $(SOURCE_FILES)
    gcc $(SOURCE_FILES) -o bestfit -DBEST_FIT -DJOB_MAX=$N

w: $(SOURCE_FILES)
    gcc $(SOURCE_FILES) -o worstfit -DWORST_FIT -DJOB_MAX=$N

clean:
    rm -f  firstfit nextfit bestfit worstfit

需要说明的是,用数组来保存空闲区和非空闲区,在next fit中,由于遍历的位置记录的是空闲区的数组下标,所以当新空闲区插入时,会从新插入的分区开始遍历。如果想要严格地实现“从上次遍历结束得位置”开始搜索,可以记录下空闲区起始地址,然后通过地址来判断next fit的起始地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yilonglucky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值