零零散散學算法之淺析內存管理的方式

解析內存管理的方式

正文

       說到內存分配,我們立刻就會想到malloc()、calloc()等申請內存的接口,說到內存分配的算法,我們會想到Buddy和Slab等分配算法。那麼你有沒有思考過,申請的內存是如何管理的呢?管理的方式都有哪些?這就是本文將要討論的。

       本文將介紹兩種內存管理的方法:鏈表法和比特位法。

第零節 問題初始化


       假設現有一坨大小爲M的內存,我們將它分爲N塊,那麼每塊的大小就是BLOCK_SIZE = M/N,如下圖所示:

第一節 鏈表法


       所謂鏈表法內存管理,就是說將已經分好的一坨內存分成了許多連續的小塊,然後將每個小塊以鏈表的形式串起來。如下圖:

       從圖中可看到,我們在每個小塊中添加了名爲link的鏈表節點,它表示爲:
struct list_head
{
    struct list_head *next, *prev;
};
附註:在內核中該鏈表爲雙向鏈表,不過在上圖中爲了簡潔,我將其表示爲單鏈表。

       於是,我們就可以用一個名爲head的頭結點將這些小塊串聯起來了。當我們使用時,只需從鏈表上摘一個即可,用完之後就可還回。利用鏈表來管理內存的優點有以下兩點:

       1. 即用即拿,用完即還(方便快捷):就是說當我們需要在這坨申請好的內存中使用一個或者幾個小塊時,我們就可根據需要,從鏈表上摘下來一個或者幾個,用完之後直接還回鏈表中即可。

       2. 管理流與數據流的融合與分離(節省空間):當我們利用鏈表法管理內存時,我們只需知道每個塊的link,這樣我們就能利用link來管理每個塊,我們說它們是融合的;當你要使用某個塊時,將其從鏈表中摘下來,這個時候我們就用這個塊來進行數據流操作,對於link我們並不關心,在這個角度上我們說它們是分離的。不論融合與分離,我們在操作時並沒有用到額外的空間,而是在每個塊的內部解決了管理流與數據流。

       好了,這就是鏈表法內存管理。節末,我還是給出鏈表法的代碼:
/**
 *  鏈表法內存管理:內存初始化

 *  addr: 表示塊的起始地址
 *  block_size: 表示每個塊的大小
 *  block_number: 表示塊的個數
 */
void MemoryInit(void* addr, unsigned long block_size, unsigned int block_number)
{
    int	i = 0;
    struct list_head *link = (struct list_head*)addr;

    for(; i < block_number; i++)
    {
        list_add_tail(link, head);//添加到鏈表尾部
        addr += block_size;
        link = (struct list_head*)addr;
    }
}
/**
 *  鏈表法內存管理:內存塊分配
 */
void* alloc_blkmem(void)
{
    struct list_head *link = NULL;
    if(!list_empty(head))//鏈表不爲空
    {
        link = head->next;
        list_del_init(link);//從鏈表中摘除
    }
    return link;
}
/**
 *  鏈表法內存管理:內存塊釋放
 *
 *  addr: 表示塊的起始地址
 */
void free_blkmem(void* addr)
{
    struct list_head *link = (struct list_head*)addr;
    list_add_tail(link, head);//還回到鏈表中
}

第二節 比特位法


       和鏈表法相比,比特位法就更簡單了。比特位的思想很簡單,就是說當某個塊沒有被使用時,我們讓該塊對應位置的bit位爲0,當這個塊被使用時,就將它的bit位置爲1。如下圖:

       比特位法的確很直觀,這是它的優點,但是和鏈表法相比,它在時間和空間上都不及鏈表法。我們來看看:

       在時間上:鏈表法是即用即拿,而比特位法則不然,它必須對bit表進行遍歷,當bit位爲0時方可取用;

       在空間上:鏈表法不需額外的空間,而比特位法則取額外的空間來存儲bitmap表,有一個塊就得對應一個bit位,當數據塊很多時,這也是一筆不消的開銷。

       雖然比特位法在時間上和空間上都不是很理想,但是它很直觀,易理解。它也很常用!

       好了,比特位法就是個這,因爲它很直觀,所以我用很簡單的幾句話就說完了。節末,還是老辦法,給出比特位法的代碼,縱然它很簡單!
/** 設置bitmap的指定位
 *
 *  src: 表示bitmap
 *  index:表示指定位
 */
void bitmap_set_bit(void *src, unsigned int index)
{
    unsigned short*    data_bitmap = (unsigned short *)src;
    data_bitmap[index] |= 1 << index;
}
/** 清除bitmap的指定位
 *
 *  src: 表示bitmap
 *  index:表示指定位
 */
void bitmap_clear_bit(void *src, unsigned int index)
{
    unsigned short*    data_bitmap = (unsigned short *)src;
    data_bitmap[index]  &=  ~(1 << index);
}

第三節 結束語


       想想、寫寫、畫畫......

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