• 操作系统第5次实验报告:内存管理


    • 姓名:巫艳珍
    • 学号:201821121034
    • 班级:计算1812

    1. 记录内存空间使用情况

    • 记录内存当前空间的使用情况,用指针的形式,分别将空闲分区表和进程使用链表打印出:

    • 进程使用了哪些空间,包括pid,大小,起始地址,进程名,next指向下一分区

    2. 记录空闲分区

    根据实验PPT给出的各部分的结构体分区

    • 空闲分区表分区大小以及起始地址,next指向下一分区的地址

    • 初始化空闲分区链表

    3. 内存分配算法

    最佳适应算法(Best Fit):
      它从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使碎片尽量小。为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一个满足要求的自由分区分配。该算法保留大的空闲区,但造成许多小的空闲区。
    实现代码如下,排序算法:
    void rearrange_BF(){
        //最佳适应算法,空闲分区按大小从小到大排序
        if(free_block == NULL || free_block->next == NULL)
            return;
        FBT *t1,*t2,*head;
        head = free_block;
        for(t1 = head->next;t1;t1 = t1->next){
            for(t2 = head;t2 != t1;t2=t2->next){
                if(t2->size > t2->next->size){
                    int tmp = t2->start_addr;
                    t2->start_addr = t2->next->start_addr;
                    t2->next->start_addr = tmp;
                    tmp = t2->size;
                    t2->size = t2->next->size;
                    t2->next->size = tmp;
                }
            }
        }
    }

    4. 内存释放算法

    进程终止,释放内存,如何释放,如何更新内存空闲分区表。给出算法源代码,并解释。

    //释放链表节点
    int dispose(AB *free_ab){
        /*释放ab数据结构节点*/
        AB *pre,*ab;
        if(free_ab == allocated_block_head){
            //如果要是释放第一个节点
            allocated_block_head = allocated_block_head->next;
            free(free_ab);
            return 1;
        }
        pre = allocated_block_head;
        ab = allocated_block_head->next;
        while(ab!=free_ab){
            pre = ab;
            ab = ab->next;
        }
        pre->next = ab->next;
        free(ab);
        return 2;
    }
    //更新分区表
    int free_mem(AB *ab){
    //将已分配区归还
    int algorithm = ma_algorithm;
    FBT *fbt,*pre,*work;
    fbt = (FBT*)malloc(sizeof(FBT));
    if(!fbt) return -1;
    fbt->size = ab->size;
    fbt->start_addr = ab->start_addr;
    
    //插至末尾
    work = free_block;
    if(work == NULL){
    free_block = fbt;
    fbt->next == NULL;
    }else{
    while(work ->next != NULL){
    work = work->next;
    }
    fbt->next = work->next;
    work->next = fbt;
    }
    //重新排布
    rearrange_BF();
    //合并分区
    pre = free_block;
    while(pre->next){
    work = pre->next;
    if(pre->start_addr + pre->size == work->start_addr ){
    pre->size = pre->size + work->size;
    pre->next = work->next;
    free(work);
    continue;
    }else{
    pre = pre->next;
    }
    }
    //按照当前算法排序,即最佳适配算法
    rearrange(ma_algorithm);
    return 1;
    }
    //找到pid对应的链表节点
    AB *find_process(int pid){
    AB *tmp = allocated_block_head;
    while(tmp != NULL){
    if(tmp->pid == pid){
    return tmp;
    }
    tmp = tmp->next;
    }
    printf("e[0;31;1m 查找失败! e[0m
    ",pid);
    return NULL;
    }
    //杀死进程
    int kill_process(int pid){
    AB *ab;
    ab = find_process(pid);
    if(ab!=NULL){
    free_mem(ab); //释放ab所表示的分配表
    dispose(ab); //释放ab数据结构节点
    return 0;
    }else{
    return -1;
    }
    }

    首先释放链表结点,利用free()不断释放结点,更新分区表,进行可能的合并,将释放的结点放置在空闲分区的末结点,对空闲的链表进行排列,使用的是BF算法,若空闲区相邻,则做合并的操作,然后将空闲链表按照BF算法进行排序。

    5. 运行结果

    (1)产生测试数据

    随机为3个进程分配、释放内存10次以上,即随机产生10组以上数据:(进程Pi 分配内存大小) 或者 (进程Pi结束)

     

     

     

     

    (2)解释结果

    每一次内存分配或释放,内存的示意图是怎样的。给出4组分析即可。

    •  内存大小设为1024,创建进程pro1,并分配内存为57

    • 创建进程pro3,起始地址为57,大小为82

    •  分别释放pro1和pro2之后创建进程pro2,大小为79:

    •  采用BF算法,为三个进程分配空间,pro3大小为83,pro2从地址83开始,大小为46,pro1从地址120开始,大小为102,剩余内存为802。释放了pro1之后再进行分配,从地址120开始

    测试的代码(部分函数在前文):

    int main(int argc, char const *argv[]){
        int flag1,flag2; 
        int total=0;  
        free_block = init_free_block(mem_size); //初始化空闲区  
        Pro pro[3];//存放要加载的进程数为3 
        init_program(pro,3);//初始化进程 
        srand( (unsigned)time( NULL ) );  
        
        for(int i=0;i<DATA_NUM;++i)
        { 
            flag1=rand()%2;
            int count=0; 
            for(int j=0;j<3;++j){
                if(pro[j].pid!=-1)
                    count++;
            } 
            if((count==3 && flag1==0)||total==10)
                flag1=1; 
            if(count==0 && flag1==1)
                flag1=0;
            if(flag1==0)//为进程分配内存 
            {
                //随机一个未分配内存的进程 
                do{
                    flag2=rand()%3;
                }while(pro[flag2].pid!=-1);
                new_process(pro[flag2]);//分配内存空间 
                pro[flag2].pid=pid;
                total++;
                view();
            }
            else//释放进程占用的内存空间 
            {
                //随机找一个可释放进程 
                do{
                    flag2=rand()%3;
                }while(pro[flag2].pid==-1);
                kill_process(pro[flag2].pid);//释放内存空间 
                pro[flag2].pid=-1;
                view();//显示内存使用情况 
            }
        }
    }
    
    //初始化空闲分区链表
    FBT *init_free_block(int mem_size){
        FBT *fb;
        fb = (FBT*)malloc(sizeof(FBT));
        if(fb==NULL){
            printf("无内存
    ");
            return NULL;
        }
        fb->size = mem_size;
        fb->start_addr = MEM_START;
        fb->next = NULL;
        return fb;
    }
    
    //更新分区表
    int free_mem(AB *ab){
        /* 将ab所表示的已分配区归还,并进行可能的合并 */
        int algorithm = ma_algorithm;
        FBT *fbt,*pre,*work;
        fbt = (FBT*)malloc(sizeof(FBT));
        if(!fbt) return -1;
        fbt->size = ab->size;
        fbt->start_addr = ab->start_addr;
    
        //插至末尾
        work = free_block;
        if(work == NULL){
            free_block = fbt;
            fbt->next == NULL;
        }else{
            while(work ->next != NULL){
                work = work->next;
            }
            fbt->next = work->next;
            work->next = fbt;
        }
        //按地址重新排布
        rearrange_BF();
    
        //合并可能分区;即若两空闲分区相连则合并
        pre = free_block;
        while(pre->next){
            work = pre->next;
            if(pre->start_addr + pre->size == work->start_addr ){
                pre->size = pre->size + work->size;
                pre->next = work->next;
                free(work);
                continue;
            }else{
                pre = pre->next;
            }
        }
    
        //按照当前算法排序
        rearrange(ma_algorithm);
        return 1;
    }//寻找是否有分区可以非进程分配
    int find_free_mem(int request){
        FBT *tmp = free_block;
        int mem_sum = 0;
        while(tmp){
            if(tmp->size >= request){
                //可以直接分配
                return 1;
            }
            mem_sum += tmp->size;
            tmp = tmp->next;
        }
        if(mem_sum >= request){
            //合并后分配
            return 0;
        }else{
            //没有足够的空间可供分配
            return -1;
        }
    
    }
    
    //将已分配表按起始地址从大到小排序
    void sort_AB(){
        if(allocated_block_head == NULL || allocated_block_head->next == NULL)
            return;
        AB *t1,*t2,*head;
        head = allocated_block_head;
        for(t1 = head->next;t1;t1 = t1->next){
            for(t2 = head;t2 != t1;t2=t2->next){
                if(t2->start_addr > t2->next->start_addr){
                    int tmp = t2->start_addr;
                    t2->start_addr = t2->next->start_addr;
                    t2->next->start_addr = tmp;
    
                    tmp = t2->size;
                    t2->size = t2->next->size;
                    t2->next->size = tmp;
                }
            }
        }
    }
    
    //重新分配
    void reset_AB(int start){
        AB *tmp = allocated_block_head;
        while(tmp != NULL){
            tmp->start_addr = start;
            start += tmp->size;
            tmp = tmp->next;
        }
    }
    
    void  memory_compact(){
        //进行内存紧缩
        FBT *fbttmp = free_block;
        AB *abtmp = allocated_block_head;
        //检测剩余内存
        int sum = 0;
        while(fbttmp!=NULL){
            sum += fbttmp->size;
            fbttmp = fbttmp->next;
        }
    
        //合并区块为一个
        fbttmp = free_block;
        fbttmp->size = sum;
        fbttmp->start_addr = 0;
        fbttmp->next=NULL;
        
        //释放多余分区
        FBT *pr = free_block->next;
        while(pr != NULL){
            fbttmp = pr->next;
            free(pr);
            pr = fbttmp;
        }
        //重新排序已分配空间
        sort_AB();
        reset_AB(sum);
    }
    
    //执行分配内存
    void do_allocate_mem(AB *ab){
        int request = ab->size;
        FBT *tmp = free_block;
        while(tmp != NULL){
            if(tmp->size >= request){
                //分配
                ab->start_addr = tmp->start_addr;
                int shengyu = tmp->size - request;
                tmp->size = shengyu;
                tmp->start_addr = tmp->start_addr + request;
                
                return ;
            }
            tmp = tmp->next;
        }
    }
    
    int allocate_mem(AB *ab){
        /*分配内存模块*/
        FBT *fbt,*pre;
        int request_size=ab->size;
        fbt = pre = free_block;
        int f = find_free_mem(request_size);
        if(f == -1){
            printf("空闲内存不足,内存分配失败!
    ");
            return -1;
        }else{
            if(f == 0){
                //需要内存紧缩才能分配
                memory_compact();
            }
            //执行分配
            do_allocate_mem(ab);
        }
        //重新排布空闲分区
        rearrange(ma_algorithm);
        return 1;
    } 
    
    //为进程分配内存 
    int new_process(Pro pro){
        AB *ab;
        int ret;
        ab = (AB*)malloc(sizeof(AB));
        if(!ab) exit(-5);
        ab->next=NULL;
        pid++;//记录id 
        strcpy(ab->process_name,pro.process_name);
        ab->pid = pid; 
        ab->size=pro.size+rand()%ALLOC_SIZE;//随机分配内存 
    
        ret = allocate_mem(ab);        //从空闲分区分配内存,ret==1表示分配成功
        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("e[0;31;1m 内存分配失败! e[0m
    ");
            free(ab);
            return -1;
        }
        return 3;
    }
    
    //初始化进程 
    void init_program(Pro pro[],int n)
    {
        for(int i=0;i<n;++i){
            pro[i].size=PROCESS_SIZE;
            pro[i].pid=-1;
            sprintf(pro[i].process_name,"pro%d",i+1);
        }
    }
    
    
    //利用BF算法整理空闲块 
    void rearrange(int algorithm){
        rearrange_BF();
    }

     参考链接:

    https://blog.csdn.net/u011070169/article/details/53177987

    https://github.com/City-Zero/LinuxTest/blob/master/OSex/mem_manager/mm.c

  • 相关阅读:
    SpringMVC 配置文件详解
    SpringMVC 入门demo
    SpringMVC 简介
    解决IDEA部署web项目时,jar包拷贝不全的问题
    录制 带鼠标光圈效果的视频
    Spring整合Junit4进行单元测试
    Illegal invocation with document.querySelector [duplicate]
    html-webpack-template, 一个更好的html web service插件
    Script error.解决方法
    ios9 safari currentTime audio bug
  • 原文地址:https://www.cnblogs.com/will-h/p/12898081.html
Copyright © 2020-2023  润新知