九幽ir

导航

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

  • 姓名 :万大明
  • 学号 :201821121058
  • 班级 :计算1812

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

int display_mem_usage(){
    //显示当前内存的使用情况,包括空闲分区的情况和已经分配的情况
    FBT *fbt = free_block;
    AB *ab = allocated_block_head;
    // if(fbt == NULL) return -1;
    printf("\e[0;31;1m------------------------------------------------------------------\e[0m\n");
    //显示空闲区
    printf("\e[0;32;1m空闲的内存:\e[0m\n");
    printf("\e[0;33;1m%20s %20s\e[0m\n","     start_addr","       size");
    while(fbt!=NULL){
        if(fbt->size!=0)
            printf("%20d %20d\n",fbt->start_addr,fbt->size);
        fbt = fbt->next;
    }

    //显示已分配区
    printf("\n");
    printf("\e[0;35;1m使用的内存:\e[0m\n");
    printf("\e[0;33;1m%10s %20s %20s %10s\e[0m\n","PID","ProcessName","start_addr","size");
    while(ab != NULL){
        printf("%10d %20s %20d %10d\n",ab->pid,ab->process_name,ab->start_addr,ab->size);
        ab = ab->next;
    }
    printf("\e[0;31;1m------------------------------------------------------------------\e[0m\n");
    return 0;
}

 

2. 记录空闲分区

/*描述每一个空闲块的数据结构*/
typedef struct free_block_type{
    int size;         //空闲块大小
    int start_addr;         //空闲区起始地址
    struct free_block_type *next;       //指向下一个空闲块
}FBT;
//初始化空闲分区链表
FBT *init_free_block(int mem_size){
    FBT *fb;

    fb = (FBT*)malloc(sizeof(FBT));
    if(fb==NULL){
        printf("No mem\n");
        return NULL;
    }
    fb->size = mem_size;
    fb->start_addr = DEFAULT_MEM_START;
    fb->next = NULL;
    return fb;
}

 

 

    //显示已分配区
    printf("\n");
    printf("\e[0;35;1m使用的内存:\e[0m\n");
    printf("\e[0;33;1m%10s %20s %20s %10s\e[0m\n","PID","ProcessName","start_addr","size");
    while(ab != NULL){
        printf("%10d %20s %20d %10d\n",ab->pid,ab->process_name,ab->start_addr,ab->size);
        ab = ab->next;
    }
    printf("\e[0;31;1m------------------------------------------------------------------\e[0m\n");
    return 0;
}

 

 

3. 内存分配算法

使用什么样的内存分配算法,给出算法源代码,并解释。

  • 内存分配:最佳分配、最差分配、首次适配、循环首次适配、快速适配、伙伴系统
  • 虚拟内存分配:分页、分段、段页式(实现虚拟内存分配,加10分,按30分来打分)
//为进程分配内存 
int alloc_process(Prc prc){
    AB *ab;
    int ret;
    ab = (AB*)malloc(sizeof(AB));
    if(!ab) exit(-5);
    /*为ab赋值 */ 
    ab->next=NULL;
    pid++;//记录id 
    strcpy(ab->process_name,prc.process_name);
    ab->pid = pid; 
    ab->size=prc.size+rand()%ALLOC_SIZE;//随机分配内存 

    ret = allocate_mem(ab);        //从空闲分区分配内存,ret==1表示分配成功
    if((ret == 1) && (allocated_block_head == NULL)){
        /*如果此时allocated_block_head尚未赋值,则赋值*/
        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 rearrange_FF(){
    /*首次适应算法,空闲区大小按起始地址升序排序*/
    //这里使用冒泡排序方法
    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->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;
            }
        }
    }
}

 

 

//按照最坏适应算法给新进程分配内存空间
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;
}

 

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){
    /* 将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_FF();

    //合并可能分区;即若两空闲分区相连则合并
    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;
}

 

 

5. 运行结果

int main(int argc, char const *argv[]){
    int sel1,sel2; 
    int total=0; //记录分配内存的次数 
    free_block = init_free_block(mem_size);//初始化空闲区
    Prc prc[PROCESS_NUM];//存放要加载的进程
    init_program(prc,PROCESS_NUM);//对这几个程进程进行初始化 
    srand((unsigned)time(NULL));  
    for(int i=0;i<DATA_NUM;++i)
    {
        /*
           sel1=0表示为某进程分配内存空间 
           sel1=1表示为释放某进程占用的内存空间 
        */ 
        sel1=rand()%2;
        int count=0;
        //统计三个进程中有多少个进程已经分配内存 
        for(int j=0;j<PROCESS_NUM;++j){
            if(prc[j].pid!=-1)
                count++;
        }
        //如果全部分配进程或者进程分配到达5次,那么就不能继续分配内存改为释放内存 
        if((count==PROCESS_NUM && sel1==0)||total==5)
            sel1=1;
        //如果全部未分配进程,那么就不能继续释放内存 
        if(count==0 && sel1==1)
            sel1=0;
        if(sel1==0)//为进程分配内存 
        {
            //随机找到一个未分配内存的进程 
            do{
                sel2=rand()%PROCESS_NUM;
            }while(prc[sel2].pid!=-1);
            alloc_process(prc[sel2]);//分配内存空间 
            prc[sel2].pid=pid;//改变标记 
            total++;
            display_mem_usage();//显示 
        }
        else//释放进程占用的内存空间 
        {
            //随机找到一个可释放进程 
            do{
                sel2=rand()%PROCESS_NUM;
            }while(prc[sel2].pid==-1);
            kill_process(prc[sel2].pid);//释放内存空间 
            prc[sel2].pid=-1;//改变标记 
            display_mem_usage();//显示 
        }
    }
}

 

 

 

设置初始内存为1024,

1,空闲地址分区从20开始,1024-20得到进程大小为1004.

   分配区间开始0,大小为20.

 

 2,空闲地址分区从70开始得到进程大小为1004-70=954.

      分配初始地址为20,大小50

 

 

 3,空闲地址分区从99开始得到进程大小为954-99=925.

      分配初始地址为70,大小29

 

 

 3,空闲地址分区从20开始得到进程大小为50.

      分配初始地址为0,大小20

 

posted on 2020-05-17 14:15  我不是酸柠檬与醋  阅读(198)  评论(0编辑  收藏  举报