專注電子技術(shù)學習與研究
當前位置:單片機教程網(wǎng) >> MCU設計實例 >> 瀏覽文章

內(nèi)存池的介紹與設計

作者:龔平   來源:本站原創(chuàng)   點擊數(shù):  更新時間:2014年03月14日   【字體:

在C語言中動態(tài)內(nèi)存的實現(xiàn)主要有兩種方法:
   1、通常采用malloc和free函數(shù)實現(xiàn)內(nèi)存的分配和釋放,這也是常用的方法,但是這種方式會導致內(nèi)存碎片的產(chǎn)生,特別是頻繁的分配會導致大量的內(nèi)存碎片產(chǎn)生。
   2、內(nèi)存池的使用,內(nèi)存池的基本實現(xiàn)方法主要是采用鏈表的形式將靜態(tài)的內(nèi)存空間動態(tài)的鏈接起來,這樣就能避免內(nèi)存碎片的產(chǎn)生。因此具體的鏈表組織方式就是我們在實際中應該考慮的。
 
內(nèi)存池是一系列固定大小的內(nèi)存空間,每一個內(nèi)存池主要包括很多內(nèi)存單元(具體的存儲區(qū)域)和內(nèi)存控制單元(控制對應的內(nèi)存單元),每一個內(nèi)存單元大小相同,但是具體的大小依據(jù)需要設計。而控制單元主要是實現(xiàn)每一個子內(nèi)存空間的控制,因此采用一一對應的方式,每一個具體的子內(nèi)存空間分配一個控制單元。靜態(tài)的內(nèi)存單元本來可以采用數(shù)組的方式進行控制,但是數(shù)組要求相同的數(shù)據(jù)類型,而且不便于確定那些內(nèi)存單元是可以處理,那些是不能進行處理的,而鏈表的組織方式則能夠比較清晰的確定空閑的區(qū)域,減少了判定的具體時間,對于不同的下標得計算的時間是不同的,而采用鏈表的方式則能夠?qū)崿F(xiàn)相同的速度訪問,由于不是通過一一比對的方式實現(xiàn)的,采用從空閑鏈表中彈出空閑子內(nèi)存空間的方式就能保證所有的訪問時間是相同的。
內(nèi)存池基本的結(jié)構(gòu)如圖所示:

    根據(jù)上面的圖是內(nèi)存池實現(xiàn)的基本框架圖,可以將內(nèi)存池設計為三個部分,主要是mem_pool_struct結(jié)構(gòu)體,mem_pool_node_struct結(jié)構(gòu)體以及內(nèi)存空間(buffer)。mem_pool_struct主要包含一個內(nèi)存池的基本信息。而mem_pool_node_struct則主要控制對應的內(nèi)存空間buffer。而buffer則是具體的子空間�?臻e鏈表、使用鏈表則主要是為了實現(xiàn)對多個內(nèi)存池的控制�;镜慕Y(jié)構(gòu)體定義如下:

 

    /******************************************************
     *
     *主要完成基本的內(nèi)存控制
     *該文檔主要完成結(jié)構(gòu)體和接口的設計
     *
     *******************************************************/

    #ifndef __MEM_POOL_H_H_
    #define __MEM_POOL_H_H_

    #define NAME_MAX_LENGTH 31
    /*采用宏定義實現(xiàn)內(nèi)存池的buffer和控制器的創(chuàng)建*/
    #define MEM_POOL_DECLARE(_node_name,_buffer_name,_type,count)\
        static mem_pool_node_t _node_name[count]\
        static _type _buffer_name[count]
    /*內(nèi)存池節(jié)點控制單元*/
    typedef struct {
            /*內(nèi)存塊控制器的節(jié)點*/
        dll_node_t node;
            /*指向的內(nèi)存塊起始地址*/
        address_t addr;
            /*表示該內(nèi)存塊是否被使用*/
        bool is_used;
    }mem_pool_node_t;

    /*內(nèi)存池結(jié)構(gòu)體*/
    typedef struct
    {
            /*用來鏈接不同的內(nèi)存池*/
        dll_node_t node;
            /*魔數(shù),用來檢測是否有效*/
            magic_number_t magic_number;
            /*內(nèi)存池名*/
            char name[NAME_MAX_LENGTH + 1];
            /*內(nèi)存的開始地址*/
            address_t addr_start;
            /*內(nèi)存的結(jié)束地址*/
        address_t addr_end;
            /*子內(nèi)存塊的大小*/
            size_t buffer_size;
        /*子內(nèi)存的個數(shù)*/
            size_t buffer_count;
            /*節(jié)點指針,便于操作后面而定義的*/
        mem_pool_node_t *mpool_head;
            /*用來鏈接空閑的子內(nèi)存區(qū)間,也就是與mem_pool_node_t中的node鏈接*/
            dll_t free_buffer;
        /*統(tǒng)計信息*/
            statistic_t stats_nobuf;
    }mem_pool_t,*mem_pool_handle_t;

    /*防止被C++編譯器編譯*/
    #ifdef __cplusplus
    extern "C"
    {
    #endif

    error_t mem_pool_create(const char _name[],mem_pool_handle_t *handle,
               void *node/*控制塊的指針*/,void *buffer,size_t buffer_size,
               size_t buffer_count);
    error_t mem_pool_delete(mem_pool_handle_t handle);
    void * mem_pool_buffer_alloc(mem_pool_handle_t handle);
    error_t mem_pool_buffer_free(mem_pool_handle_t handle,void *buffer);

    #ifdef __cplusplus
    }
    #endif

    #endif

由于其中該頭文件主要實現(xiàn)了幾個重要的結(jié)構(gòu)體,分別是mem_pool_t和mem_pool_node_t,分別是內(nèi)存池結(jié)構(gòu)體和內(nèi)存池子空間控制塊結(jié)構(gòu)體。

 

    /**********************************************************
     *
     *文檔用來實現(xiàn)內(nèi)存池的基本實現(xiàn)
     *
     * *******************************************************/

    #include"mem_pool_h"

    #define MPOOL_MAX_NUMBER 8
    #define MPOOL_MAX_BUFFER_COUNT 32

    /*創(chuàng)建8個內(nèi)存池*/
    static mem_pool_t g_mem_pool_t[MPOOL_MAX_NUMBER];
    /*空閑鏈表,鏈接空閑的內(nèi)存池*/
    static dll_t g_free_link;
    /*使用鏈表,鏈接正在使用的內(nèi)存池*/
    static dll_t g_used_link;


    /**********************************************************
     * 該函數(shù)主要完成將上面創(chuàng)建的八個內(nèi)存池,
     * 分配通過mem_pool_t中的node連接到空閑
     * 鏈表中。
     **********************************************************/
    static void mem_pool_init()
    {
     /*具體的依據(jù)鏈表提供的操作完成*/
    }

    /**********************************************************
     *該函數(shù)主要完成內(nèi)存池的創(chuàng)建,其中的參數(shù)主要包含
     * _name是內(nèi)存池名,
     * handle是內(nèi)存池結(jié)構(gòu)體指針的指針
     * node是子內(nèi)存控制塊數(shù)組的指針
     * buffer是自內(nèi)存塊數(shù)組的指針
     * 以上兩個參數(shù)主要通過MEM_POOL_DECLARE實現(xiàn)
     * buffer_size是指子內(nèi)存空間的大小
     * buffer_count是值子空間的個數(shù)
     *********************************************************/
     error_t mem_pool_create(const char _name[],mem_pool_handle_t *handle,
                   void *node/*控制塊的指針*/,void *buffer,size_t buffer_size,
                   size_t buffer_count)
    {
        /*
         * 主要完成mem_pool_t結(jié)構(gòu)體的填充,不需要采用malloc創(chuàng)建,
         * 而是通過鏈表彈出空間的方式實現(xiàn),將內(nèi)存池對象連接到使用鏈表
         */
      
        /*
         * 同時將各個子內(nèi)存空間的控制塊節(jié)點添加到mem_pool_t中的free_buffer中
         */
    }

    /**********************************************************
     *該函數(shù)主要是完成內(nèi)存池的刪除,實質(zhì)上也就是完成mem_pool_t
     *結(jié)構(gòu)體中參數(shù)的修改,但是需要注意的是不能刪除正在使用的內(nèi)存池
     * *******************************************************/
    error_t mem_pool_delete(mem_pool_handle_t handle)
    {
          /*
           *完成將內(nèi)存池對象從使用鏈表中移除,并將其連接到空閑鏈表
           *確保所有的子內(nèi)存空間沒有被使用
           * */
    }

    /*************************************************************
     *該函數(shù)主要是依據(jù)內(nèi)存池中的鏈表free_buffer中找出空閑的子內(nèi)存空間
     *基本的原理就是依據(jù)free_buffer找到子內(nèi)存空間的空閑塊,然后依據(jù)
     *mem_pool_node_t中的addr找到內(nèi)存空間的指針,也就得到內(nèi)存空間
     *************************************************************/
    void * mem_pool_buffer_alloc(mem_pool_handle_t handle)
    {
       /*從free_buffer中彈出空閑的子內(nèi)存空間*/
      
       /*通過mem_pool_node_t中的addr找到子內(nèi)存空間,并將狀態(tài)修改為使用*/
    }

    /*************************************************************
     * 該函數(shù)主要通過buffer的地址找到對應的子內(nèi)存控制塊,
     * 將mem_pool_node中的is_used設置為0即可
     * ***********************************************************/
    error_t mem_pool_buffer_free(mem_pool_handle_t handle,void *buffer)
    {
         /*通過buffer找到子內(nèi)存空間控制器對應的下標,
         * 然后將mem_pool_node設置為沒有使用
         * 最重要的是將該控制器節(jié)點的node壓入mem_pool_t中的free_buffer中
         * */
    }

由于關(guān)于鏈表的操作沒有實現(xiàn),本文沒有實現(xiàn)具體的操作,但是各個函數(shù)的實現(xiàn)要點都已經(jīng)給出。

內(nèi)存池沒有反復的分配和釋放,這樣就能較好的避免內(nèi)存碎片的產(chǎn)生。其實只要明白基本的模塊就能比較好的實現(xiàn)內(nèi)存池。即內(nèi)存池結(jié)構(gòu)體(mem_pool_t),結(jié)構(gòu)體中將鏈表節(jié)點作為第一個元素主要是為了快速的強制類型轉(zhuǎn)換得到新的數(shù)據(jù)類型指針。比如mem_pool_t的node可以從空閑鏈表中彈出,然后強制類型轉(zhuǎn)換既可以得到mem_pool_t的指針。內(nèi)存控制單元(mem_pool_t)的實現(xiàn)。
 
實質(zhì)上所有的操作都是基于鏈表的操作,通過內(nèi)存池結(jié)構(gòu)體中的鏈表將所有的子空間控制單元鏈接起來,實現(xiàn)了一個內(nèi)存池的操作。而外部的鏈表則實現(xiàn)了不同內(nèi)存池的操作。
 
其中的采用數(shù)組的方式進行分配空間主要是為了使后期的操作簡單,能夠依據(jù)數(shù)組的一些特性快速的實現(xiàn)內(nèi)存池空間的管理。
 
具體的可參考《專業(yè)嵌入式軟件開發(fā)》。

關(guān)閉窗口

相關(guān)文章