内存池的实现
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