• 内存分配---FF、BF、WF三种算法


       动态分区分配是根据进程的实际需要,动态的为之分配内存空间。而在实现可变分区分配时,将涉及到分区分配中

    所用的数据结构、分区分配算法和分区的分配与内存回收的过程。

        分区分配中的数据结构:(1)描述空闲块的数据结构。(2)内存块的描述。

    #define PROCESS_NAME_LEN 32    //进程名长度
    #define MIN_SLICE 10           //最小碎片的大小
    #define DEFAULT_MEM_SIZE 1024  //内存大小
    #define DEFAULT_MEM_START 0    //起始位置
    //内存分配算法
    #define MA_FF 1
    #define MA_BF 2
    #define MA_WF 3
    //描述每一个空闲块的数据结构
    struct free_block_type
    {
        int size;                      //空闲块大小
        int start_addr;                //空闲块起始位置
        struct free_block_type *next;  //指向下一个空闲块
    };
    //指向内存中空闲块链表的首地址
    struct free_block_type *free_block= NULL;
    //每个进程分配到的内存块的描述
    struct allocated_block
    {
        int pid;
        int size;         //进程大小
        int start_addr;   //进程分配到的内存块的起始地址
        char process_name[PROCESS_NAME_LEN];  //进程名
        struct allocated_block *next;         //指向下一个进程控制块
    };
    //进程分配内存块链表的首指针
    struct allocated_block *allocated_block_head= NULL;
    int free_block_count= 0;          //空闲块的个数
    int mem_size= DEFAULT_MEM_SIZE;   //内存大小
    int current_free_mem_size= 0;     //当前空闲内存大小
    int ma_algorithm= MA_FF;          //当前分配算法
    static int pid= 0;
    int flag= 0;                      //设置内存大小标志,表示内存大小是否设置

        分区分配算法:

      (1)首次适应算法(First Fit):从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给

    业,这种方法的目的在于减少查找时间。为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到

    进行排序。该算法优先使用低址部分空闲区,在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。

      (2)最佳适应算法(Best Fit):从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使

    碎片尽量小。为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一

    个满足要求的自由分区分配。该算法保留大的空闲区,但造成许多小的空闲区。

      (3)最差适应算法(Worst Fit):从全部空闲区中找出能满足作业要求的、且大小最大的空闲分区,从而使链表中

    的结点大小趋于均匀,适用于请求分配的内存大小范围较窄的系统。为适应此算法,空闲分区表(空闲区链)中的空

    闲分区按大小从大到小进行排序,自表头开始查找到第一个满足要求的自由分区分配。该算法保留小的空闲区,尽量

    减少小的碎片产生。

      下面是进行以上三种算法的实现:

    #include <stdio.h>
    #include <malloc.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define PROCESS_NAME_LEN 32    //进程名长度
    #define MIN_SLICE 10           //最小碎片的大小
    #define DEFAULT_MEM_SIZE 1024  //内存大小
    #define DEFAULT_MEM_START 0    //起始位置
    //内存分配算法
    #define MA_FF 1
    #define MA_BF 2
    #define MA_WF 3
    //描述每一个空闲块的数据结构
    struct free_block_type
    {
        int size;        //空闲块大小
        int start_addr;  //空闲块起始位置
        struct free_block_type *next;  //指向下一个空闲块
    };
    //指向内存中空闲块链表的首地址
    struct free_block_type *free_block= NULL;
    //每个进程分配到的内存块的描述
    struct allocated_block
    {
        int pid;
        int size;         //进程大小
        int start_addr;   //进程分配到的内存块的起始地址
        char process_name[PROCESS_NAME_LEN];  //进程名
        struct allocated_block *next;   //指向下一个进程控制块
    };
    //进程分配内存块链表的首指针
    struct allocated_block *allocated_block_head= NULL;
    int free_block_count= 0;          //空闲块的个数
    int mem_size= DEFAULT_MEM_SIZE;   //内存大小
    int current_free_mem_size= 0;     //当前空闲内存大小
    int ma_algorithm= MA_FF;          //当前分配算法
    static int pid= 0;
    int flag= 0;                      //设置内存大小标志,表示内存大小是否设置
    
    struct free_block_type* init_free_block(int mem_size);
    void display_menu();
    int set_mem_size();
    void set_algorithm();
    void rearrange(int algorithm);
    int rearrange_WF();
    int rearrange_BF();
    int rearrange_FF();
    int new_process();
    int allocate_mem(struct allocated_block *ab);
    void kill_process();
    int free_mem(struct allocated_block *ab);
    int dispose(struct allocated_block *free_ab);
    int display_mem_usage();
    struct allocated_block* find_process(int pid);
    int do_exit();
    int allocate_FF(struct allocated_block *ab);
    int allocate_BF(struct allocated_block *ab);
    int allocate_WF(struct allocated_block *ab);
    int allocate(struct free_block_type *pre,struct free_block_type *allocate_free_nlock,struct allocated_block *ab);
    int mem_retrench(struct allocated_block *ab);
    
    //通过内存紧缩技术给新进程分配内存空间
    int mem_retrench(struct allocated_block *ab)
    {
        struct allocated_block *allocated_work,*allocated_pre= allocated_block_head;
        struct free_block_type *free_work,*free_pre= free_block->next;
        if(allocated_pre== NULL)
            return -1;
        allocated_pre->start_addr= 0;
        allocated_work= allocated_pre->next;
        while(allocated_work!= NULL)
        {
            allocated_work->start_addr= allocated_pre->start_addr+ allocated_pre->size;
            allocated_pre= allocated_work;
            allocated_work= allocated_work->next;
        }
        free_block->start_addr= allocated_pre->start_addr+ allocated_pre->size;
        free_block->size= current_free_mem_size;
        free_work= free_pre;
        while(free_pre!= NULL)
        {
            free(free_pre);
            free_pre= free_work;
            if(free_pre!= NULL)
                free_work= free_work->next;
        }
        allocate(NULL,free_block,ab);
        return 1;
    }
    
    //给新进程分配内存空间
    int allocate(struct free_block_type *pre,struct free_block_type *allocate_free_block,struct allocated_block *ab)
    {
        struct allocated_block *p= allocated_block_head;
        ab->start_addr= allocate_free_block->start_addr;
        if(allocate_free_block->size-ab->size< MIN_SLICE)
        {
            ab->size= allocate_free_block->size;
            if(pre!= NULL)
            {
                pre->next= allocate_free_block;
            }
            else
            {
                free_block= allocate_free_block->next;
            }
            free(allocate_free_block);
        }
        else
        {
            allocate_free_block->start_addr+= ab->size;
            allocate_free_block->size-= ab->size;
        }
        if(p== NULL)
        {
            allocated_block_head= ab;
        }
        else
        {
            while(p->next!= NULL)
                p= p->next;
            p->next= ab;
        }
        current_free_mem_size-= ab->size;
        if(current_free_mem_size== 0)
            free_block= NULL;
        return 0;
    }
    
    //按照最坏适应算法给新进程分配内存空间
    int allocate_WF(struct allocated_block *ab)
    {
        int ret;
        struct free_block_type *wf= free_block;
        if(wf== NULL)
            return -1;
        if(wf->size>= ab->size)
            allocate(NULL,wf,ab);
        else if(current_free_mem_size>= ab->size)
            ret= mem_retrench(ab);
        else
            ret= -2;
        rearrange_WF();
        return ret;
    }
    
    //按照最佳适应算法给新进程分配内存空间
    int allocate_BF(struct allocated_block *ab)
    {
        int ret;
        struct free_block_type *pre= NULL,*bf= free_block;
        if(bf== NULL)
            return -1;
        while(bf!= NULL)
        {
            if(bf->size>= ab->size)
            {
                ret= allocate(pre,bf,ab);
                break;
            }
            pre= bf;
            pre= pre->next;
        }
        if(bf== NULL&&current_free_mem_size> ab->size)
            ret= mem_retrench(ab);
        else
            ret= -2;
        rearrange_BF();
        return ret;
    }
    
    //按照首次适应算法给新进程分配内存空间
    int allocate_FF(struct allocated_block *ab)
    {
        int ret;
        struct free_block_type *pre= NULL,*ff= free_block;
        if(ff== NULL)
            return -1;
        while(ff!= NULL)
        {
            if(ff->size>= ab->size)
            {
                ret= allocate(pre,ff,ab);
                break;
            }
            pre= ff;
            pre= pre->next;
        }
        if(ff== NULL&&current_free_mem_size> ab->size)
            ret= mem_retrench(ab);
        else
            ret= -2;
        rearrange_FF();
        return ret;
    }
    
    //分配内存模块
    int allocate_mem(struct allocated_block *ab)
    {
        int ret;
        struct free_block_type *fbt,*pre;
        int request_size= ab->size;
        fbt= pre= free_block;
        switch(ma_algorithm)
        {
            case MA_FF:
                ret= allocate_FF(ab);
                break;
            case MA_BF:
                ret= allocate_BF(ab);
                break;
            case MA_WF:
                ret= allocate_WF(ab);
                break;
            default:
                break;
        }
        return ret;
    }
    
    //创建一个新进程
    int new_process()
    {
        struct allocated_block *ab;
        int size;
        int ret;
        ab= (struct allocated_block*)malloc(sizeof(struct allocated_block));
        if(!ab)
            exit(-5);
        ab->next= NULL;
        pid++;
        sprintf(ab->process_name,"PROCESS-%02d",pid);//将格式化的数据写入某字符串中
        ab->pid= pid;
        printf("Memory for %s:",ab->process_name);
        for(;;)
        {
            scanf("%d",&size);
            getchar();
            if(size> 0)
            {
                ab->size= size;
                break;
            }
            else
                printf("The size have to greater than zero!Please input again!");
        }
        ret= allocate_mem(ab);
        if((ret== 1)&&(allocated_block_head== NULL))  //如果此时未赋值,则赋值
        {
            allocated_block_head= ab;
            return 1;
        }
        else if(ret== 1)  //分配成功,将该已分配块的描述插入已分配链表
        {
            ab->next= allocated_block_head;
            allocated_block_head= ab;
            return 2;
        }
        else if(ret== -1)  //分配不成功
        {
            printf("Allocation fail.
    ");
            free(ab);
            return -1;
        }
        return 3;
    }
    
    //退出程序并释放空间
    int do_exit()
    {
        struct allocated_block *allocated_ab,*allocated_pre;
        struct free_block_type *free_ab,*free_pre;
        free_pre= free_block;
        allocated_pre= allocated_block_head;
        if(free_pre!= NULL)
        {
            free_ab= free_pre->next;
            while(free_ab!= NULL)
            {
                free(free_pre);
                free_pre= free_ab;
                free_ab= free_ab->next;
            }
        }
        if(allocated_pre!= NULL)
        {
            allocated_ab= allocated_pre->next;
            while(allocated_ab!= NULL)
            {
                free(allocated_pre);
                allocated_pre= allocated_ab;
                allocated_ab= allocated_ab->next;
            }
        }
        allocated_ab= allocated_ab->next;
        return 0;
    }
    
    //在进程分配链表中寻找指定进程
    struct allocated_block* find_process(int pid)
    {
        struct allocated_block *ab= allocated_block_head;
        if(ab== NULL)
        {
            printf("Here?111
    ");
            return NULL;
        }
        while(ab->pid!= pid&&ab->next!= NULL)
            ab= ab->next;
        if(ab->next== NULL&&ab->pid!= pid)
        {
            printf("Here?222
    ");
            return NULL;
        }
        return ab;
    }
    
    //显示当前内存的使用情况,包括空闲区的情况和已经分配的情况
    int display_mem_usage()
    {
        struct free_block_type *fbt= free_block;
        struct allocated_block *ab= allocated_block_head;
        printf("-------------------------------------------------------------
    ");
        printf("Free Memory:
    ");
        printf("%20s %20s
    ","     start_addr","     size");
        while(fbt!= NULL)
        {
            printf("%20d %20d
    ",fbt->start_addr,fbt->size);
            fbt= fbt->next;
        }
        printf("
    Used Memory:
    ");
        printf("%10s %20s %10s %10s
    ","PID","ProcessName","start_addr","size");
        while(ab!= NULL)
        {
            printf("%10d %20s %10d %10d
    ",ab->pid,ab->process_name,ab->start_addr,ab->size);
            ab= ab->next;
        }
        printf("-------------------------------------------------------------
    ");
        return 1;
    }
    
    //释放ab数据结构结点
    int dispose(struct allocated_block *free_ab)
    {
        struct allocated_block *pre,*ab;
        if(free_block== NULL)
            return -1;
        if(free_ab== allocated_block_head)   //如果要释放第一个结点
        {
            allocated_block_head= allocated_block_head->next;
            free(free_ab);
        }
        else
        {
            pre= allocated_block_head;
            ab= allocated_block_head->next; 
            //找到free_ab
            while(ab!= free_ab)
            {
                pre= ab;
                ab= ab->next;
            }
            pre->next= ab->next;
            free(ab);
        }
        return 1;
    }
    
    //将ab所表示的已分配区归还,并进行可能的合并
    int free_mem(struct allocated_block *ab)
    {
        int algorithm= ma_algorithm;
        struct free_block_type *fbt,*pre,*work;
        fbt= (struct free_block_type*)malloc(sizeof(struct free_block_type));
        if(!fbt)
            return -1;
        pre= free_block;
        fbt->start_addr= ab->start_addr;
        fbt->size= ab->size;
        fbt->next= NULL;
        if(pre!= NULL)
        {
            while(pre->next!= NULL)
                pre= pre->next;
            pre->next= fbt;
        }
        else
        {
            free_block= fbt;
        }
        rearrange_FF();
        pre= free_block;
        work= pre->next;
        while(work!= NULL)
        {
            if(pre->start_addr+ pre->size== work->start_addr)
            {
                pre->size+= work->size;
                free(work);
                work= pre->next;
            }
            else
            {
                pre= work;
                work= work->next;
            }
        }
        current_free_mem_size+= ab->size;
        return 1;
    }
    
    //删除进程,归还分配的存储空间,并删除描述该进程内存分配的结点
    void kill_process()
    {
        struct allocated_block *ab;
        int pid;
        printf("Kill Process,pid=");
        scanf("%d",&pid);
        getchar();
        ab= find_process(pid);
        if(ab!= NULL)
        {
            free_mem(ab);  //释放ab所表示的分配区
            dispose(ab);   //释放ab数据结构结点
        }
    }
    
    //按FF算法重新整理内存空闲块链表,按空闲块首地址排序
    int rearrange_FF()
    {
        struct free_block_type *head= free_block;
        struct free_block_type *forehand,*pre,*rear;
        int i;
        if(head== NULL)
            return -1;
        for(i= 0;i< free_block_count-1;i++)
        {
            forehand= head;
            pre= forehand->next;
            rear= pre->next;
            while(pre->next!= NULL)
            {
                if(forehand== head&&forehand->start_addr>= pre->start_addr)
                {
                    //比较空闲链表中第一个空闲块与第二个空闲块的开始地址的大小
                    head->next= pre->next;
                    pre->next= head;
                    head= pre;
                    forehand= head->next;
                    pre= forehand->next;
                    rear= pre->next;
                }
                else if(pre->start_addr>= rear->start_addr)
                {
                    //比较链表中其它相邻两个结点的开始地址的大小
                    pre->next= rear->next;
                    forehand->next= rear;
                    rear->next= pre;
                    forehand= rear;
                    rear= pre->next;
                }
                else
                {
                    forehand= pre;
                    pre= rear;
                    rear= rear->next;
                }
            }
        }
        return 0;
    }
    
    //按BF算法重新整理内存空闲块链表,按空闲块大小从小到大排序
    int rearrange_BF()
    {
        struct free_block_type *head= free_block;
        struct free_block_type *forehand,*pre,*rear;
        int i;
        if(head== NULL)
            return -1;
        for(i= 0;i< free_block_count-1;i++)
        {
            forehand= head;
            pre= forehand->next;
            rear= pre->next;
            while(pre->next!= NULL)
            {
                if(forehand== head&&forehand->size<= pre->size)
                {
                    //比较空闲链表中第一个空闲块与第二个空闲块的空间的大小
                    head->next= pre->next;
                    pre->next= head;
                    head= pre;
                    forehand= head->next;
                    pre= forehand->next;
                    rear= pre->next;
                }
                else if(pre->size<= rear->size)
                {
                    //比较链表中其它相邻两个结点的空间的大小
                    pre->next= rear->next;
                    forehand->next= rear;
                    rear->next= pre;
                    forehand= rear;
                    rear= pre->next;
                }
                else
                {
                    forehand= pre;
                    pre= rear;
                    rear= rear->next;
                }
            }
        }
        return 0;
    }
    
    //按WF算法重新整理内存空闲块链表,按空闲块大小从大到小排序
    int rearrange_WF()
    {
        struct free_block_type *head= free_block;
        struct free_block_type *forehand,*pre,*rear;
        int i;
        if(head== NULL)
            return -1;
        for(i= 0;i< free_block_count-1;i++)
        {
            forehand= head;
            pre= forehand->next;
            rear= pre->next;
            while(pre->next!= NULL)
            {
                if(forehand== head&&forehand->size>= pre->size)
                {
                    //比较空闲链表中第一个空闲块与第二个空闲块空间的大小
                    head->next= pre->next;
                    pre->next= head;
                    head= pre;
                    forehand= head->next;
                    pre= forehand->next;
                    rear= pre->next;
                }
                else if(pre->size>= rear->size)
                {
                    //比较链表中其它相邻两个结点的空间的大小
                    pre->next= rear->next;
                    forehand->next= rear;
                    rear->next= pre;
                    forehand= rear;
                    rear= pre->next;
                }
                else
                {
                    forehand= pre;
                    pre= rear;
                    rear= rear->next;
                }
            }
        }
        return 0;
    }
    
    //按指定的算法整理内存空闲块链表
    void rearrange(int algorithm)
    {
        switch(algorithm)
        {
            case MA_FF:
                rearrange_FF();
                break;
            case MA_BF:
                rearrange_BF();
                break;
            case MA_WF:
                rearrange_WF();
                break;
        }
    }
    
    //设置当前的分配算法
    void set_algorithm()
    {
        int algorithm;
        //system("clear");
        printf("	1-First Fit
    ");   //首次适应算法
        printf("	2-Best Fit
    ");    //最佳适应算法
        printf("	3-Worst Fit
    ");   //最坏适应算法
        printf("Please choose(1-3):");
        for(;;)
        {
            scanf("%d",&algorithm);
            getchar();
            if(algorithm>= 1&&algorithm<= 3)
            {
                ma_algorithm= algorithm;
                break;
            }
            else
            {
                printf("
    Cannot input %d,Please input 1-3:",algorithm);
            }
        }
        rearrange(ma_algorithm);
    }
    
    //设置内存的大小
    int set_mem_size()
    {
        int size;
        if(flag!= 0)     //防止重复设置
        {
            printf("Cannont set memory size again
    ");
            return 0;
        }
        printf("Total memory size=");
        for(;;)
        {
            scanf("%d",&size);
            getchar();
            if(size> 0)
            {
                current_free_mem_size= size;
                mem_size= size;
                free_block->size= mem_size;
                break;
            }
            else
            {
                printf("The size must greater than zero!Please input again:");
            }
        }
        flag= 1;    //内存大小已经设置
        return 1;
    }
    
    //显示主菜单
    void display_menu()
    {
        printf("
    ");
        //system("clear");
        printf("1-Set memory size(default= %d)
    ",DEFAULT_MEM_SIZE);
        printf("2-Select memory allocation algorithm
    ");
        printf("3-New process
    ");
        printf("4-Terminate a process
    ");
        printf("5-Display memory usage
    ");
        printf("0-Exit
    ");
    }
    
    //初始化空闲块,默认为一块,可以指定大小及起始地址
    struct free_block_type* init_free_block(int mem_size)
    {
        struct free_block_type *fb;
        fb= (struct free_block_type*)malloc(sizeof(struct free_block_type));
        if(fb== NULL)
        {
            printf("No mem
    ");
            return NULL;
        }
        current_free_mem_size= mem_size;
        fb->size= mem_size;
        fb->start_addr= DEFAULT_MEM_START;
        fb->next= NULL;    //首地址指向NULL
        return fb;
    }
    
    int main()
    {
        char choice;
        pid= 0;
        free_block= init_free_block(mem_size);
        while(1)
        {
            display_menu();
            fflush(stdin);
            choice= getchar();
            getchar();
            switch(choice)
            {
                case '1':     //设置内存大小
                    set_mem_size();
                    break;
                case '2':     //设置算法
                    set_algorithm();
                    flag= 1;
                    break;
                case '3':     //创建新进程
                    new_process();
                    flag= 1;
                    break;
                case '4':     //删除进程
                    kill_process();
                    flag= 1;
                    break;
                case '5':     //显示内存使用
                    display_mem_usage();
                    flag= 1;
                    break;
                case '0':     //释放链表并退出
                    do_exit();
                    exit(0);
                default:
                    break;
            }
        }
    }
  • 相关阅读:
    JQuery插件,轻量级表单模型验证(续 二)
    关于DateTimeOffset的爱恨情仇
    JQuery插件,轻量级表单模型验证(续 一)
    asp.net 远程模型验证
    JQuery插件,轻量级表单模型验证
    Ef Core增加Sql方法
    初识依赖注入
    Core下简易WebApi
    sql语句实现行转列练习
    sql语句基本查询操作
  • 原文地址:https://www.cnblogs.com/XNQC1314/p/9065236.html
Copyright © 2020-2023  润新知