挖一下那些年的东东(模拟内存申请与释放C语言)

#include<stdio.h>

#include<stdlib.h>

#include<malloc.h>

#define Type int



typedef struct MBox{

    struct MBox * pre;

    int size;

    struct MBox * next;

    int begin;

    int tag;                        //是否被使用 0是空闲 1是占用

    int end;

}MBox,*pMBox;

//存储内存块的信息



typedef struct Memory{

    int size;

    Type *base;                        //真正的内存

    pMBox first;                    //指向第一个内存块

}Memory,*pMemory;

//一条内存



void fill(pMemory pM,int s,int e,int j){

    for(s;s<=e;s++)

        pM->base[s]=j;

}

//填充是否使用

//s是开始填充位置,e为结束填充位置

//j是0或1

//0是空闲内存,1是已使用内存



int init(pMemory pM){

    int i;

    printf("Well,please enter the memory size:");    

    scanf("%d",&pM->size);

    if(pM->base=(Type *)malloc(sizeof(Type)*(pM->size))){

        pM->first=(pMBox)malloc(sizeof(MBox));

        pM->first->begin=0;

        pM->first->size=pM->size;

        pM->first->next=pM->first->pre=NULL;

        pM->first->end=pM->size-1;

        pM->first->tag=0;

        for(i=0;i<pM->size;i++)

            pM->base[i]=0;

        fill(pM,pM->first->begin,pM->first->end,0);

        return 1;

    }

    else return 0;

}

//初始化内存条信息



int ask_m(pMemory pM,int size){

    int i,flag=0;

    pMBox pMB1,pMB2;

    for(pMB1=pMB2=pM->first;pMB1!=NULL;pMB1=pMB1->next){

        pMB2=pMB1;

        if(pMB2->tag==0 && pMB2->size>=size){

            flag=1;

            break;

        }

    }

    

    if(pMB2->size<size)                            //找不到就返回假,请求失败

        return 0;

    else if(pMB2->size>size){                    //找到比请求所需的大的内存,分割

        pMB1=(pMBox)malloc(sizeof(MBox));

        pMB1->next=pM->first;

        pMB1->pre=NULL;

        pMB1->next->pre=pMB1;

        pM->first=pMB1;



        pMB1->begin=pMB2->begin;

        pMB1->end=pMB1->begin+size-1;

    

        pMB2->begin=pMB1->end+1;

        pMB2->size=pMB2->size-size;



        pMB1->size=size;

        pMB1->tag=1;

        fill(pM,pMB1->begin,pMB1->end,1);

        return 1;

    }

    else if(pMB2->size==size){                    //找到大小刚好合适的直接使用

        pMB2->tag=1;

        fill(pM,pMB2->begin,pMB2->end,1);

        return 1;

    }

}

//请求内存



int free_m(pMemory pM,int MBox_num){

    int i,flag=0;

    pMBox pMB1,pMB2,pMB3;

    if(MBox_num==0)

        return 0;

    for(i=1,pMB1=pM->first;i<MBox_num && pMB1!=NULL;i++,pMB1=pMB1->next);    //索引需要释放的位置



    if(pMB1==NULL || pMB1->tag==0)                    //空闲块,直接返回

        return 0;

    else {

        for(pMB2=pMB1;pMB2!=NULL;pMB3=pMB2,pMB2=pMB2->next){    //寻找第MBox_num要释放的内存块,flag标记是否已经找到可合并内存块

            if(pM->first==pMB1)                                    //如果是第一个,则处理与其他有区别

                pM->first=pMB1->next;                            //因为涉及到内存条的first

            if(pMB2->begin==pMB1->end+1 && pMB2->tag==0){        //寻找是否能找到合并的,条件大家推导下

                pMB2->begin=pMB1->begin;

                pMB2->size=pMB2->size+pMB1->size;

                flag=1;

                break;

            }else if(pMB2->end+1==pMB1->begin && pMB2->tag==0){    //也是寻找可合并的

                if(pM->first==pMB1)

                    pM->first=pMB1->next;

                pMB2->end=pMB1->end;

                pMB2->size=pMB2->size+pMB1->size;

                flag=1;

                break;

            }

        }

        if(pMB2==NULL)    //当pMB2为NULL时,pMB2等于它的上一个备份pMB3

            pMB2=pMB3;

        if(flag==0){    //flag==0就是没有合并的情况

            if(i==1){    //i==1意味着是第1个内存块要被处理,涉及到pM->first

                pMB2->next=pMB1;

                pM->first=pMB1->next;

                pMB1->next->pre=NULL;

                pMB1->pre=pMB2;

                pMB1->next=NULL;

            }else {

                pMB2->next=pMB1;

                pMB1->pre->next=pMB1->next;

                pMB1->next->pre=pMB1->pre;

                pMB1->pre=pMB2;

                pMB1->next=NULL;

            }

        }

        fill(pM,pMB1->begin,pMB1->end,0);

        if(flag==1)

            free(pMB1);

        else pMB1->tag=0;

    }

    Man_m(pM);

}

//释放内存

//MBox_num是释放的占用块的索引



void Travel(pMemory pM){

    int i;

    printf("\nTraveling the mermory!\n");

    for(i=0;i<pM->size;i++)

        printf("%d ",pM->base[i]);

    printf("\n\n");

}

//遍历内存使用情况



void showBox(pMemory pM){

    int i=1;

    pMBox pB=pM->first;

    printf("\nTraveling the MBox!\n");

    while(pB!=NULL){

        printf("*************************  MBox%d:0x%.8x  *****************************\n",i++,pB);

        printf("* pre         size        next        begin       tag         end        *\n");

        printf("* 0x%.8x ",pB->pre);

        printf(" %.10d ",pB->size);

        printf(" 0x%.8x ",pB->next);

        printf(" %.10d ",pB->begin);

        printf(" %.10d ",pB->tag);

        printf(" %.10d *\n",pB->end);

        printf("**************************************************************************\n\n");

        pB=pB->next;

    }

}

//遍历内存块信息



int Man_m(pMemory pM){

    pMBox pMB1,pMB2,pMB3;

    MBox MB;

    int i,j,k;

    for (pMB3=pM->first;pMB3->tag==1 && pMB3!=NULL;pMB3=pMB3->next);    //因为空闲块都在后面

                                                                        //所以找到第一块空的,后面的都是空的了

    if(pMB3==NULL)

        return 0;                                                        //这是找不到占用块的情况



    for(pMB2=pMB3,i=1;pMB2->next!=NULL;i++,pMB2=pMB2->next);            //这是计算一共有多少个空闲块



    if(i==1)

        return 0;

    else {

        for(j=1;j<i;j++){                                                //简单用冒泡排序把小的空闲块排到前面

            pMB1=pMB3;

            pMB2=pMB3->next;

            for(k=1;k<i;k++,pMB1=pMB1->next,pMB2=pMB2->next){

                if(pMB2->size<pMB1->size){

                    MB.size=pMB1->size;

                    MB.begin=pMB1->begin;

                    MB.end=pMB1->end;



                    pMB1->size=pMB2->size;

                    pMB1->begin=pMB2->begin;

                    pMB1->end=pMB2->end;



                    pMB2->size=MB.size;

                    pMB2->begin=MB.begin;

                    pMB2->end=MB.end;

                }

            }

        }

    }

}

//整理空闲块,保持小空闲块在前,大的空闲在后

//易于请求内存时先利用小的,再拆分大的



int main(){

    Memory m;

    init(&m);

    ask_m(&m,2);

    Travel(&m);

    showBox(&m);



    ask_m(&m,4);

    Travel(&m);

    showBox(&m);



    free_m(&m,2);

    Travel(&m);

    showBox(&m);



    ask_m(&m,2);

    Travel(&m);

    showBox(&m);

    return 0;

}

 

转载于:https://my.oschina.net/august1996/blog/676730

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值