程序员

内存池的实现

2017-02-17  本文已影响61人  perryn

基本的架构设计:

这里写图片描述
/*************************************************************************
        > 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

上一篇下一篇

猜你喜欢

热点阅读