美文网首页程序员
内存池的实现

内存池的实现

作者: perryn | 来源:发表于2017-02-17 18:03 被阅读61次

    基本的架构设计:

    这里写图片描述
    /*************************************************************************
            > File Name: mem_pool.h
            > Author: perrynzhou
            > Mail: 715169549@qq.com
            > Created Time: Wed 21 Sep 2016 02:51:56 AM HKT
     ************************************************************************/
    
    #ifndef _MEM_POOL_H
    #define _MEM_POOL_H
    #include <stdint.h>
    typedef struct _MemPool MemPool;
    MemPool *CreatedMemPool ();
    void *AllocMem (uint32_t size, MemPool * mp);
    void FreeMem (void *ptr, MemPool * mp);
    void DestroyMemPool (MemPool * mp);
    #endif
    
    /*************************************************************************
            > File Name: mem_pool.c
            > Author: perrynzhou
            > Mail: 715169549@qq.com
            > Created Time: Wed 21 Sep 2016 02:59:39 AM HKT
     ************************************************************************/
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "mem_pool.h"
    typedef struct _MemNode
    {
            struct _MemNode *Next;
            uint32_t Size;
            char Buf[];
    } __attribute__ ((__packed__)) MemNode;
    struct _MemPool
    {
            MemNode **FreeBlocks;           //the array of used blocks in this pool
            MemNode **UsedBlocks;
    } __attribute__ ((__packed__));
    
    //define max type 
    #define MAXTYPE 64
    //align 8 byte
    #define ALIGN_SIZE 8
    //------avoid using -> 
    #define FreeBlocks(T)    ((T)->FreeBlocks)
    #define UsedBlocks(T)    ((T)->UsedBlocks)
    //MemNode 
    #define Next(T)        ((T)->Next)
    #define Size(T)        ((T)->Size)
    #define Buf(T)         ((T)->Buf)
    inline uint32_t RoundUp (uint32_t size)
    {
            return ((size + (ALIGN_SIZE - 1)) & ~(ALIGN_SIZE - 1));
    }
    
    //memory aligin whit 8 byte
    inline uint32_t Index (uint32_t size)
    {
            return ((RoundUp (size) / ALIGN_SIZE) - 1);
    }
    
    //remove link of target memnode
    static void _Relink (MemNode * first, MemNode * mn)
    {
            if (mn != NULL)
            {
                    while (first != NULL)
                    {
                            MemNode *prev = NULL;
                            if (first == mn)
                            {
                                    if (Next (first) == NULL)
                                    {
                                            prev = NULL;
                                    }
                                    else
                                    {
                                            prev = Next (first);
                                    }
                                    break;
                            }
                            else
                            {
                                    prev = first;
                            }
                            first = Next (first);
                    }
            }
    }
    
    //check memory block is exists in usedblocks list
    static int _IsUsed (MemNode * mn, uint32_t index, MemPool * mp)
    {
            if (mp == NULL || mn == NULL)
            {
                    return -1;
            }
            MemNode *free = FreeBlocks (mp)[index];
            if (free == NULL)
            {
                    return 0;
            }
            while (free != NULL)
            {
                    if (free == mn)
                    {
                            return -1;
                    }
                    free = Next (free);
            }
            return 0;
    }
    
    static void *_Alloc (uint32_t size, MemPool * mp)
    {
            if (mp == NULL)
            {
                    return NULL;
            }
            uint32_t curSize = RoundUp (size);
            uint32_t iIndex = (curSize / ALIGN_SIZE) - 1;
            MemNode *mn = malloc (sizeof (*mn) + curSize);
            char *ptr = NULL;
            if (mn != NULL)
            {
                    Next (mn) = NULL;
                    Size (mn) = curSize;
                    Next (mn) = UsedBlocks (mp)[iIndex];
                    UsedBlocks (mp)[iIndex] = mn;
                    ptr = Buf (mn);
                    memset (ptr, 0, curSize);
                    fprintf (stdout, "......index =%d,system malloc sizeof(memnode) =%d,size=%d,next=%p,buf=%p\n", iIndex, sizeof (*mn), Size (mn), Next (mn), Buf (mn));
            }
            return (char *) ptr;
    }
    
    MemPool *CreateMemPool ()
    {
            MemPool *mp = (MemPool *) malloc (sizeof (*mp));
            if (mp != NULL)
            {
                    UsedBlocks (mp) = (MemNode **) malloc (sizeof (MemNode *) * MAXTYPE);
                    FreeBlocks (mp) = (MemNode **) malloc (sizeof (MemNode *) * MAXTYPE);
                    int iIndex = 0;
                    for (iIndex = 0; iIndex < MAXTYPE; iIndex++)
                    {
                            UsedBlocks (mp)[iIndex] = FreeBlocks (mp)[iIndex] = NULL;
                            fprintf (stdout, "...UseBlocks[%d] =%p,FreeBlocks[%d] =%p\n", iIndex, UsedBlocks (mp)[iIndex], iIndex, FreeBlocks (mp)[iIndex]);
                    }
                    fprintf (stdout, "...init memory pool\n");
            }
            return mp;
    }
    
    //malloc memory from memory pool
    void *AllocMem (uint32_t size, MemPool * mp)
    {
            if (mp == NULL)
            {
                    return NULL;
            }
            MemNode *target = NULL;
            char *ptr = NULL;
            uint32_t index = Index (size);
            if (index >= MAXTYPE)
            {
                    return NULL;
            }
            if (FreeBlocks (mp)[index] == NULL)
            {
                    ptr = _Alloc (size, mp);
            }
            else
            {
                    target = FreeBlocks (mp)[index];
                    FreeBlocks (mp)[index] = Next (target);
                    Next (target) = NULL;
                    Next (target) = UsedBlocks (mp)[index];
                    UsedBlocks (mp)[index] = target;
                    ptr = Buf (target);
                    fprintf (stdout, "index=%d...malloc from pool MemNode =%p,next=%p,size=%d\n", index, target, Next (target), Size (target));
            }
            return ptr;
    }
    
    //put unused block to memory pool
    void FreeMem (void *block, MemPool * mp)
    {
            if (mp != NULL && block != NULL)
            {
                    MemNode *mn = (MemNode *) (block - sizeof (*mn));
                    uint32_t index = (Size (mn) / ALIGN_SIZE) - 1;
                    if (_IsUsed (mn, index, mp) != -1)
                    {
                            MemNode *first = UsedBlocks (mp)[index];
                            if (first == mn)
                            {
                                    UsedBlocks (mp)[index] = Next (first);
                            }
                            else
                            {
                                    _Relink (first, mn);
                            }
                            Next (mn) = NULL;
                            memset (Buf (mn), 0, Size (mn));
    
                            Next (mn) = FreeBlocks (mp)[index];
                            FreeBlocks (mp)[index] = mn;
                            fprintf (stdout, "......put unused block to pool,MemNode =%p,size=%d\n", mn, Size (mn));
                    }
            }
    }
    
    void PtrMemPoolUsed (MemPool * mp)
    {
            int i = 0;
            for (; i < MAXTYPE; i++)
            {
                    MemNode *used = UsedBlocks (mp)[i];
                    while (used != NULL)
                    {
                            fprintf (stdout, "     %d.....Used MemNode =%p,Size=%d,Next=%p\n", i, used, Size (used), Next (used));
                            used = Next (used);
                    }
            }
    }
    
    void PtrMemPoolFree (MemPool * mp)
    {
            int i = 0;
            for (; i < MAXTYPE; i++)
            {
                    MemNode *free = FreeBlocks (mp)[i];
                    while (free != NULL)
                    {
                            fprintf (stdout, "     %d.....Free MemNode =%p,Size=%d,Next=%p\n", i, free, Size (free), Next (free));
                            free = Next (free);
                    }
            }
    }
    
    void DestroyMemPool (MemPool * mp)
    {
            if (mp != NULL)
            {
                    MemNode *usedMemNode = UsedBlocks (mp)[0];
                    MemNode *freeMemNode = FreeBlocks (mp)[0];
                    while (usedMemNode != NULL)
                    {
                            MemNode *next = Next (usedMemNode);
                            free (usedMemNode);
                            usedMemNode = next;
                    }
                    while (freeMemNode != NULL)
                    {
                            MemNode *next = Next (freeMemNode);
                            free (freeMemNode);
                            freeMemNode = next;
                    }
                    if (usedMemNode != NULL)
                    {
                            usedMemNode = NULL;
                    }
                    if (freeMemNode != NULL)
                    {
                            freeMemNode = NULL;
                    }
                    //my_log(p,"...free all blocks from pool %s","");
            }
            if (mp != NULL)
            {
                    fprintf (stdout, "...free all blocks from pool %p\n", mp);
                    free (mp);
                    mp = NULL;
            }
    }
    
    /*************************************************************************
            > File Name: mem_pool_test.c
            > Author: perrynzhou
            > Mail: 715169549@qq.com
            > Created Time: Thu 22 Sep 2016 01:37:31 AM HKT
     ************************************************************************/
    
    #include <stdio.h>
    #include <unistd.h>
    #include "mem_pool.h"
    int main (void)
    {
            MemPool *mp = (MemPool *) CreateMemPool ();
            int max = 20, i;
            void *target[20] = { NULL };
            for (i = 0; i < max; i++)
            {
    
                    target[i] = AllocMem ((i + 1) * (rand () % 20) + 7, mp);
                    if (i % 5 == 0)
                    {
    
                            FreeMem (target[i], mp);
    
                    }
            }
            PtrMemPoolUsed (mp);
            PtrMemPoolFree (mp);
            fprintf (stdout, "------------------------------------split-------------------------\n");
            for (i = 0; i < max; i++)
            {
                    if (i % 4 == 0)
                    {
                            fprintf (stdout, "*********************freemem********************************\n");
                            FreeMem (target[6], mp);
                            PtrMemPoolUsed (mp);
                            PtrMemPoolFree (mp);
    
                    }
            }
            fprintf (stdout, "----------------------end--------------------\n");
            DestroyMemPool (mp);
            return 0;
    }
    

    测试结果:

    $ ./a.out
    ...UseBlocks[0] =(nil),FreeBlocks[0] =(nil)   -- (0+1)*8 byte
    ..........................
    ...UseBlocks[63] =(nil),FreeBlocks[63] =(nil)  --(63+1) * 8 byte
    ...init memory pool
    ......index =0,system malloc sizeof(memnode) =12,size=8,next=(nil),buf=0x1b4b45c
    ......put unused block to pool,MemNode =0x1b4b450,size=8
    ......index =1,system malloc sizeof(memnode) =12,size=16,next=(nil),buf=0x1b4b47c
    ......index =2,system malloc sizeof(memnode) =12,size=24,next=(nil),buf=0x1b4b4ac
    ......put unused block to pool,MemNode =0x1b4b4a0,size=24
    index=2...malloc from pool MemNode =0x1b4b4a0,next=(nil),size=24
    ......index =2,system malloc sizeof(memnode) =12,size=24,next=0x1b4b4a0,buf=0x1b4b4dc
    ......put unused block to pool,MemNode =0x1b4b4d0,size=24
    index=0...malloc from pool MemNode =0x1b4b450,next=(nil),size=8
    ......index =1,system malloc sizeof(memnode) =12,size=16,next=0x1b4b470,buf=0x1b4b50c
    ......put unused block to pool,MemNode =0x1b4b500,size=16
    index=1...malloc from pool MemNode =0x1b4b500,next=0x1b4b470,size=16
    ......index =4,system malloc sizeof(memnode) =12,size=40,next=(nil),buf=0x1b4b53c
    ......put unused block to pool,MemNode =0x1b4b530,size=40
    ......index =1,system malloc sizeof(memnode) =12,size=16,next=0x1b4b500,buf=0x1b4b57c
    ......index =0,system malloc sizeof(memnode) =12,size=8,next=0x1b4b450,buf=0x1b4b5ac
    ......put unused block to pool,MemNode =0x1b4b5a0,size=8
    ......index =1,system malloc sizeof(memnode) =12,size=16,next=0x1b4b570,buf=0x1b4b5cc
    index=0...malloc from pool MemNode =0x1b4b5a0,next=0x1b4b450,size=8
    ......put unused block to pool,MemNode =0x1b4b5a0,size=8
    index=4...malloc from pool MemNode =0x1b4b530,next=(nil),size=40
    index=2...malloc from pool MemNode =0x1b4b4d0,next=0x1b4b4a0,size=24
    ......put unused block to pool,MemNode =0x1b4b4d0,size=24
    index=0...malloc from pool MemNode =0x1b4b5a0,next=0x1b4b450,size=8
    ......index =0,system malloc sizeof(memnode) =12,size=8,next=0x1b4b5a0,buf=0x1b4b5fc
    ......put unused block to pool,MemNode =0x1b4b5f0,size=8
    index=2...malloc from pool MemNode =0x1b4b4d0,next=0x1b4b4a0,size=24
    ......index =1,system malloc sizeof(memnode) =12,size=16,next=0x1b4b5c0,buf=0x1b4b61c
    ......put unused block to pool,MemNode =0x1b4b610,size=16
    ......index =3,system malloc sizeof(memnode) =12,size=32,next=(nil),buf=0x1b4b64c
         0.....Used MemNode =0x1b4b5a0,Size=8,Next=0x1b4b450
         0.....Used MemNode =0x1b4b450,Size=8,Next=(nil)
         1.....Used MemNode =0x1b4b5c0,Size=16,Next=0x1b4b570
         1.....Used MemNode =0x1b4b570,Size=16,Next=0x1b4b500
         1.....Used MemNode =0x1b4b500,Size=16,Next=0x1b4b470
         1.....Used MemNode =0x1b4b470,Size=16,Next=(nil)
         2.....Used MemNode =0x1b4b4d0,Size=24,Next=0x1b4b4a0
         2.....Used MemNode =0x1b4b4a0,Size=24,Next=(nil)
         3.....Used MemNode =0x1b4b640,Size=32,Next=(nil)
         4.....Used MemNode =0x1b4b530,Size=40,Next=(nil)
         0.....Free MemNode =0x1b4b5f0,Size=8,Next=(nil)
         1.....Free MemNode =0x1b4b610,Size=16,Next=(nil)
    ------------------------------------split-------------------------
    *********************freemem********************************
    ......put unused block to pool,MemNode =0x1b4b500,size=16
         0.....Used MemNode =0x1b4b5a0,Size=8,Next=0x1b4b450
         0.....Used MemNode =0x1b4b450,Size=8,Next=(nil)
         1.....Used MemNode =0x1b4b5c0,Size=16,Next=0x1b4b570
         1.....Used MemNode =0x1b4b570,Size=16,Next=0x1b4b500
         1.....Used MemNode =0x1b4b500,Size=16,Next=0x1b4b610
         1.....Used MemNode =0x1b4b610,Size=16,Next=(nil)
         2.....Used MemNode =0x1b4b4d0,Size=24,Next=0x1b4b4a0
         2.....Used MemNode =0x1b4b4a0,Size=24,Next=(nil)
         3.....Used MemNode =0x1b4b640,Size=32,Next=(nil)
         4.....Used MemNode =0x1b4b530,Size=40,Next=(nil)
         0.....Free MemNode =0x1b4b5f0,Size=8,Next=(nil)
         1.....Free MemNode =0x1b4b500,Size=16,Next=0x1b4b610
         1.....Free MemNode =0x1b4b610,Size=16,Next=(nil)
    *********************freemem********************************
         0.....Used MemNode =0x1b4b5a0,Size=8,Next=0x1b4b450
         0.....Used MemNode =0x1b4b450,Size=8,Next=(nil)
         1.....Used MemNode =0x1b4b5c0,Size=16,Next=0x1b4b570
         1.....Used MemNode =0x1b4b570,Size=16,Next=0x1b4b500
         1.....Used MemNode =0x1b4b500,Size=16,Next=0x1b4b610
         1.....Used MemNode =0x1b4b610,Size=16,Next=(nil)
         2.....Used MemNode =0x1b4b4d0,Size=24,Next=0x1b4b4a0
         2.....Used MemNode =0x1b4b4a0,Size=24,Next=(nil)
         3.....Used MemNode =0x1b4b640,Size=32,Next=(nil)
         4.....Used MemNode =0x1b4b530,Size=40,Next=(nil)
         0.....Free MemNode =0x1b4b5f0,Size=8,Next=(nil)
         1.....Free MemNode =0x1b4b500,Size=16,Next=0x1b4b610
         1.....Free MemNode =0x1b4b610,Size=16,Next=(nil)
    *********************freemem********************************
         0.....Used MemNode =0x1b4b5a0,Size=8,Next=0x1b4b450
         0.....Used MemNode =0x1b4b450,Size=8,Next=(nil)
         1.....Used MemNode =0x1b4b5c0,Size=16,Next=0x1b4b570
         1.....Used MemNode =0x1b4b570,Size=16,Next=0x1b4b500
         1.....Used MemNode =0x1b4b500,Size=16,Next=0x1b4b610
         1.....Used MemNode =0x1b4b610,Size=16,Next=(nil)
         2.....Used MemNode =0x1b4b4d0,Size=24,Next=0x1b4b4a0
         2.....Used MemNode =0x1b4b4a0,Size=24,Next=(nil)
         3.....Used MemNode =0x1b4b640,Size=32,Next=(nil)
         4.....Used MemNode =0x1b4b530,Size=40,Next=(nil)
         0.....Free MemNode =0x1b4b5f0,Size=8,Next=(nil)
         1.....Free MemNode =0x1b4b500,Size=16,Next=0x1b4b610
         1.....Free MemNode =0x1b4b610,Size=16,Next=(nil)
    *********************freemem********************************
         0.....Used MemNode =0x1b4b5a0,Size=8,Next=0x1b4b450
         0.....Used MemNode =0x1b4b450,Size=8,Next=(nil)
         1.....Used MemNode =0x1b4b5c0,Size=16,Next=0x1b4b570
         1.....Used MemNode =0x1b4b570,Size=16,Next=0x1b4b500
         1.....Used MemNode =0x1b4b500,Size=16,Next=0x1b4b610
         1.....Used MemNode =0x1b4b610,Size=16,Next=(nil)
         2.....Used MemNode =0x1b4b4d0,Size=24,Next=0x1b4b4a0
         2.....Used MemNode =0x1b4b4a0,Size=24,Next=(nil)
         3.....Used MemNode =0x1b4b640,Size=32,Next=(nil)
         4.....Used MemNode =0x1b4b530,Size=40,Next=(nil)
         0.....Free MemNode =0x1b4b5f0,Size=8,Next=(nil)
         1.....Free MemNode =0x1b4b500,Size=16,Next=0x1b4b610
         1.....Free MemNode =0x1b4b610,Size=16,Next=(nil)
    *********************freemem********************************
         0.....Used MemNode =0x1b4b5a0,Size=8,Next=0x1b4b450
         0.....Used MemNode =0x1b4b450,Size=8,Next=(nil)
         1.....Used MemNode =0x1b4b5c0,Size=16,Next=0x1b4b570
         1.....Used MemNode =0x1b4b570,Size=16,Next=0x1b4b500
         1.....Used MemNode =0x1b4b500,Size=16,Next=0x1b4b610
         1.....Used MemNode =0x1b4b610,Size=16,Next=(nil)
         2.....Used MemNode =0x1b4b4d0,Size=24,Next=0x1b4b4a0
         2.....Used MemNode =0x1b4b4a0,Size=24,Next=(nil)
         3.....Used MemNode =0x1b4b640,Size=32,Next=(nil)
         4.....Used MemNode =0x1b4b530,Size=40,Next=(nil)
         0.....Free MemNode =0x1b4b5f0,Size=8,Next=(nil)
         1.....Free MemNode =0x1b4b500,Size=16,Next=0x1b4b610
         1.....Free MemNode =0x1b4b610,Size=16,Next=(nil)
    ----------------------end--------------------
    ...free all blocks from pool 0x1b4b010
    
    

    相关文章

      网友评论

        本文标题:内存池的实现

        本文链接:https://www.haomeiwen.com/subject/znmlwttx.html