動態內存分配

內存分配是在預先設定的未使用內存堆中分配出需求的空間,然後將該空間起始地址返回給調用者,操作系統內核有一套自己的數據結構描述、記錄哪些空間範圍已經被分配、哪些未使用,不同操作系統有不同的內存分配策略。


一種內存堆分配方法(摘自《嵌入式網絡那些事》):

void *mem_malloc(mem_size_t size)
{
    mem_size_t ptr, ptr2;        //局部變量,保存內存塊起始地址偏移量
    struct mem *mem, *mem2;
    if(size == 0){
        return NULL;
    }
    size = LWIP_MEM_ALIGN_SIZE(size);   //將size修正爲內存對齊字節數的整數倍
    if(size < MIN_SIZE_ALIGNED){
        size = MIN_SIZE_ALIGNED;
    }
    if(size > MEN_SIZE_ALIGNED){
        return NULL;
    }
    
    //從lfree開始遍歷,找出第一個長度大於size的空閒內存塊
    for(ptr = (u8_t*)lfree-ram; ptr < MEM_SIZE_ALIGNED-size;
                                                ptr = ((struct mem*)&ram[ptr])->next)
    {
        mem = (struct mem*)&ram[ptr];  
        //若該內存塊未使用,且其空間不小於(用戶請求大小+系統結構體mem)
        if((!mem->used)&&(mem->next-(ptr+SIZEOF_STRUCT_MEM)) >= size){
            //接下來判斷是將該內存塊全部分配給用戶,還是截取其中的一部分,判斷標準是:
            //若做截取,判斷剩下的部分是否能組成一個最小的內存塊,即是否能剩下
            //SIZEOF_STRUCT_MEM+MIN_SIZE_ALIGNED的大小
            if(mem->next-(ptr+SIZEOF_STRUCT_MEM) >= 
                                (size+SIZEOF_STRUCT_MEM+MIN_SIZE_ALIGNED)){
                //需截取
                ptr2 = ptr+SIZEOF_STRUCT_MEM+size;  //分配後剩餘空間起始處偏移量
                mem2 = (struct mem*)&ram[ptr2];
                mem2->used = 0;
                mem2->next = mem->next;  //將空閒塊插入到原空閒內存塊鏈表中
                mem2->prev = ptr;
                mem->next = ptr2;
                mem->used = 1;
                if(mem2->next != MEM_SIZE_ALIGNED){
                    ((struct mem*)&ram[mem2->next])->prev = ptr2;
                }
                MEM_STATS_INC_USED(used, (size+SIZEOF_STRUCT_MEM));//增加全變量
            }else {//直接分配,不用截取
                mem->used = 1;
                MEM_STATS_INC_USED(used, mem->next-((u8_t*)mem-ram));//增加全變量
            }
            //分配完畢
            if(mem == lfree){ //lfree指向的內存塊被分配出去時,更新lfree
                while(lfree->used&&lfree != ram_end){
                    lfree = (struct mem*)&ram[lfree->next];
                }
            }
            return (u8_t*)mem + SIZEOF_STRUCT_MEM; //分配成功,返回可用內存塊起始區域
        }//此內存塊不滿足要求,下一個for循環
    }//所有內存塊都不滿足要求
    
    return NULL;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章