操作系统第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\n",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("无内存\n");
        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("空闲内存不足,内存分配失败!\n");
        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\n");
        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

posted @ 2020-05-16 00:33  王尔  阅读(742)  评论(0编辑  收藏  举报