記憶體 Clerk三

來源:互聯網
上載者:User

已經實現了自己的malloc函數Imalloc,但是記憶體管理還是需要calloc,free,relloc函數來管理記憶體:
calloc:在記憶體的動態儲存裝置區中分配n個長度為size的連續空間,函數返回一個指向分配起始地址的指標,並將記憶體空間置0,在32位機上是4bytes一個記憶體塊大小;如果分配不成功,返回NULL。

 void *Icalloc(size_t number,size_t size){    size_t *new;    size_t s4,i;    new=Imalloc(number*size);    if(new){        s4=align4(number*size)<<2;        for(i=0;i<s4;i++)            new[i]=0;    }    return (new);} 

在free的時候有兩個問題需要解決:驗證需要被free的塊,避免記憶體片段。
驗證需要被free塊需要做兩件事:是否在之前malloc所分配的地區內;該地址確實是通過malloc分配的。問題一比較地址就可以了。問題二有兩個方法:在meta-data中添加magic number,free的時候檢查該值;添加一個magic pointer,指向資料區的第一個位元組。採用方法二。在避免片段的時候需要合并小的記憶體塊,需要將該記憶體塊的前後合并起來,但是單向鏈表難以操作,所以講meta-data改為雙向鏈表。由於資料結構改變,相應的需要修改之前的函數。

typedef struct s_block *p_block;struct s_block{    size_t size;    p_block next;    p_block prev;    int free;    void *ptr;    char data[1];};

驗證地址合法性:

p_block get_block(void *p){    char *temp;    temp=p;    return(p=temp-=META_DATA_SIZE);}int valid_addr(void *p){    if(base){        if(p>base&&p<sbrk(0))            return (p==(get_block(p)->ptr));    }    return (0);}

合并記憶體塊:

p_block fusion(p_block b){    if(b->next&&b->next->free){        b->size+=META_DATA_SIZE+b->next->size;        b->next=b->next->next;          if(b->next)            b->next->prev=b;    }    return (b);}

free函數:
驗證指標通過:
1. 擷取記憶體塊的地址
2. 標記free為1
3. 如果存在之前的塊並且為free為1,合并這兩塊記憶體
4. 同樣處理最後一塊
5. 如果是最後一塊記憶體塊
6. 如果沒有記憶體塊,返回最初狀態(base 置為NULL)
如果驗證不通過就什麼也不處理。
int brk(const void *addr)將break設定到addr處

void Ifree(void *p){    p_block b;    if(valid_addr(p)){        b=get_block(p);        b->free=1;        if(b->prev&&b->prev->free)            b=fusion(b->prev);        if(b->next)            fusion(b);        else{            if(b->prev)                b->prev->next=NULL;            else                base=NULL;            brk(b);        }    }}

realloc 函數:釋放老的動態記憶體塊,按照給出的尺寸分配新的動態記憶體塊,老的記憶體塊的內容盡量複製到新的記憶體塊

複製記憶體:

void copy_block(p_block src,p_block dst){    int *sdata,*ddata;    size_t i;    sdata=src->ptr;    ddata=dst->ptr;    for(i=0;i*4<src->size&&i*4<dst->size;i++)        ddata[i]=sdata[i];}

重寫realloc:
1. 使用Imalloc分配新的記憶體塊
2. 從舊的記憶體塊複製內容到新的記憶體塊
3. 釋放老的記憶體塊
4. 返回新的指標
如果:
1. size沒變,或者額外size足夠,則不操作
2. 如果縮小,可以split
3. 如果next是free然後提供了足夠的空間大小,可以合并在split

void *Irealloc(void *p,size_t size){    size_t s;    p_block b,new;    void *newp;    if(!p)        return (Imalloc(size));    if(valid_addr(p)){        s=align4(size);        b=get_block(p);        if(b->size>=s){            if(b->size-s>=(META_DATA_SIZE+4))                split_block(b,s);        }else{            if(b->next&&b->next->free&&              (b->size+META_DATA_SIZE+b->next->size)>=s){                fusion(b);                if(b->size-s>=(META_DATA_SIZE+4))                split_block(b,s);            }else{                newp=Imalloc(s);                if(!newp)                    return (NULL);                new=get_block(newp);                copy_block(b,new);                    Ifree(p);                return(newp);            }        }        return (p);    }    return (NULL);}

至此,已基本完成了malloc,free,realloc,calloc的功能,但也只是簡單粗略的實現,但也還有很多地方值得修改的,比如文章http://blog.jobbole.com/75656/描述的那樣:
1. 分配記憶體較大塊記憶體時,使用mmap替代sbrk
2. 維護多個鏈表,提高尋找效率
也有後面需要做的就是http://www.skywind.me/blog/archives/1480中提到的一些功能和觀點:
1. 做好標記和保護,避免二次釋放
2. 修改尋找演算法,尋找最合適大小的記憶體塊上
3. 夥伴演算法
4. freelist
5. slab代替Freelist
6. 混合分配策略
7. 實現地址著色
8. 最佳化緩衝競爭

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.