Chinaunix首页 | 论坛 | 博客
  • 博客访问: 350470
  • 博文数量: 94
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 606
  • 用 户 组: 普通用户
  • 注册时间: 2015-09-30 08:58
个人简介

x

文章分类

全部博文(94)

文章存档

2019年(4)

2018年(10)

2017年(26)

2016年(38)

2015年(16)

我的朋友

分类: LINUX

2015-09-30 09:54:49

前不久做过一个项目,在ubuntu中使用libpcap捕获网络数据包并处理,用到多线程并发处理,将捕获的数据包数据拷贝至任务缓冲池中,发现频繁使用malloc()/free(),效率极其底下,后来发现malloc()是阻塞函数,于是去研究内存池。网上找到一篇好文章:http://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html,里面算法的实现简单易用。每次从内核动态申请一块较大的内存,如5MB、10MB等等,然后设计算法去使用它,下面是结合这篇文章实现的C代码。

点击(此处)折叠或打开

  1. // tool_momery_pool.h
  2. #ifndef __MEMORY_POOL_H__
  3. #define __MEMORY_POOL_H__

  4. typedef unsigned int   MM_UINT32;
  5. typedef unsigned char  MM_UCHAR;
  6. typedef unsigned long  MM_ULONG;
  7. typedef unsigned short MM_USHORT;

  8. /* Memory Block */
  9. typedef struct MEMORY_BLOCK_s
  10. {
  11.     MM_UINT32 wAllUnitSize; /* all unit size in the block */
  12.     MM_UINT32 wFreeUnitNum; /* free unit num in the block */
  13.     MM_UINT32 wFirstUnitID; /* the first free unit id in the block */
  14.     struct MEMORY_BLOCK_s *pstNext; /* the next block addr */
  15.     MM_UCHAR acData[1]; /* the last byte in the structure,
  16.                                            also the first byte in the first unit*/
  17. }MEMORY_BLOCK_t;

  18. /* Memory Pool */
  19. typedef struct MEMORY_POOL_s
  20. {
  21.     MEMORY_BLOCK_t *pstMemoryBlock; /* block linklist head */
  22.     MM_UINT32 wEveryUnitSize; /* every unit memory size */
  23.     MM_UINT32 wInitUnitNum; /* alloc unit num when alloc the first block */
  24.     MM_UINT32 wGrowUnitNum; /* alloc unit num after alloc the first block */
  25.     pthread_cond_t stMemPoolCond; /* memory pool cond */
  26.     pthread_mutex_t stMemPoolLock; /* memory pool lock */
  27. }MEMORY_POOL_t;


  28. #if 0
  29. #define MM_AllocMemory(pstMemoryPool, wMemSize) \
  30. ({ \
  31.     void *pRetVal = NULL; \
  32.     MM_UCHAR *pTemp = NULL; \
  33.     /* static int iAllocCount = 0; */ \
  34.     MEMORY_BLOCK_t *pstMemoryBlock = NULL; \
  35.                                                                                              \
  36.     if(NULL != pstMemoryPool && wMemSize <= pstMemoryPool->wEveryUnitSize) \
  37.     { \
  38.         pthread_mutex_lock(&pstMemoryPool->stMemPoolLock); \
  39.                                                                                              \
  40.         /* TODO[1]: no memory block, alloc memory block first */ \
  41.         if(NULL == pstMemoryPool->pstMemoryBlock) \
  42.         { \
  43.             pstMemoryBlock = MM_AllocMemoryBlock(pstMemoryPool->wInitUnitNum, \
  44.                     pstMemoryPool->wEveryUnitSize); \
  45.             if(NULL != pstMemoryBlock) \
  46.             { \
  47.                 pstMemoryBlock->pstNext = pstMemoryPool->pstMemoryBlock; \
  48.                 pstMemoryPool->pstMemoryBlock = pstMemoryBlock; \
  49.                                                                                              \
  50.                 pRetVal = (void *)pstMemoryBlock->acData; \
  51.             } \
  52.         } \
  53.         else \
  54.         { \
  55.             /* TODO[2]: try to find exsit memory unit */ \
  56.             pstMemoryBlock = pstMemoryPool->pstMemoryBlock; \
  57.             while(NULL != pstMemoryBlock && 0 == pstMemoryBlock->wFreeUnitNum) \
  58.             { \
  59.                 pstMemoryBlock = pstMemoryBlock->pstNext; \
  60.             } \
  61.                                                                                              \
  62.             if(NULL != pstMemoryBlock) \
  63.             { \
  64.                 pTemp = pstMemoryBlock->acData + \
  65.                         (pstMemoryBlock->wFirstUnitID * pstMemoryPool->wEveryUnitSize); \
  66.                                                                                              \
  67.                 pstMemoryBlock->wFirstUnitID = *(MM_UINT32 *)pTemp; \
  68.                 pstMemoryBlock->wFreeUnitNum --; \
  69.                                                                                              \
  70.                 pRetVal = (void *)pTemp; \
  71.             } \
  72.             else \
  73.             { \
  74.                 /* TODO[3]: no more memory to alloc, then alloc memory block */ \
  75.                 pstMemoryBlock = MM_AllocMemoryBlock(pstMemoryPool->wGrowUnitNum, \
  76.                         pstMemoryPool->wEveryUnitSize); \
  77.                                                                                              \
  78.                 if(NULL != pstMemoryBlock) \
  79.                 { \
  80.                     pstMemoryBlock->pstNext = pstMemoryPool->pstMemoryBlock; \
  81.                     pstMemoryPool->pstMemoryBlock = pstMemoryBlock; \
  82.                                                                                              \
  83.                     pRetVal = (void *)pstMemoryBlock->acData; \
  84.                 } \
  85.             } \
  86.         } \
  87.         pthread_mutex_unlock(&pstMemoryPool->stMemPoolLock); \
  88.                                                                                              \
  89.         /* tool_printf("iAllocCount = %d\n", ++iAllocCount); */ \
  90.     } \
  91.                                                                                              \
  92.     pRetVal; \
  93. })
  94. #endif

  95. extern MEMORY_POOL_t *MM_CreateMemoryPool(MM_UINT32 wEveryUnitSize, \
  96.         MM_UINT32 wInitUnitNum, MM_UINT32 wGrowUnitNum, MM_UINT32 wPoolAlignment);
  97. extern MEMORY_BLOCK_t *MM_AllocMemoryBlock(MM_UINT32 wUnitNum, MM_UINT32 wUnitSize);
  98. extern void *MM_AllocMemory(MEMORY_POOL_t *pstMemoryPool, MM_UINT32 wMemSize);
  99. extern int MM_FreeMemory(MEMORY_POOL_t *pstMemoryPool, void *pFreeMem);

  100. #endif

点击(此处)折叠或打开

  1. // tool_memory_pool.c
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <pthread.h>

  8. #include "tool_memory_pool.h"

  9. MEMORY_POOL_t *MM_CreateMemoryPool(MM_UINT32 wEveryUnitSize, \
  10.         MM_UINT32 wInitUnitNum, MM_UINT32 wGrowUnitNum, MM_UINT32 wPoolAlignment)
  11. {
  12.     MEMORY_POOL_t *pstMemoryPool = NULL;                    

  13.     if(wEveryUnitSize <= 0 || wInitUnitNum <= 0 || wGrowUnitNum <= 0)
  14.         return NULL;

  15.     pstMemoryPool = (MEMORY_POOL_t *)malloc(sizeof(MEMORY_POOL_t));
  16.     if(NULL == pstMemoryPool)
  17.         return NULL;

  18.     memset(pstMemoryPool, 0, sizeof(MEMORY_POOL_t));

  19.     pstMemoryPool->pstMemoryBlock = NULL;
  20.     pstMemoryPool->wInitUnitNum = wInitUnitNum;
  21.     pstMemoryPool->wGrowUnitNum = wGrowUnitNum;
  22.     pthread_cond_init(&pstMemoryPool->stMemPoolCond, NULL);
  23.     pthread_mutex_init(&pstMemoryPool->stMemPoolLock, NULL);

  24.     if(wEveryUnitSize > 4)    
  25.     {
  26.         pstMemoryPool->wEveryUnitSize = (wEveryUnitSize + (wPoolAlignment - 1)) & \
  27.                                         ~(wPoolAlignment - 1);
  28.     }
  29.     else if(wEveryUnitSize <= 2)
  30.     {
  31.         pstMemoryPool->wEveryUnitSize = 2;
  32.     }
  33.     else
  34.     {
  35.         pstMemoryPool->wEveryUnitSize = 4;
  36.     }

  37.     return pstMemoryPool;
  38. }

  39. MEMORY_BLOCK_t *MM_AllocMemoryBlock(MM_UINT32 wUnitNum, MM_UINT32 wUnitSize)
  40. {
  41.     MM_UINT32 i = 0;
  42.     MM_UCHAR *pTemp = NULL;
  43.     MEMORY_BLOCK_t *pstMemoryBlock = NULL;

  44.     if(wUnitNum <= 0 || wUnitSize <= 0)
  45.         return NULL;


  46.     /* alloc memory block */
  47.     pTemp = (MM_UCHAR *)malloc(sizeof(MEMORY_BLOCK_t) + wUnitNum * wUnitSize);
  48.     if(NULL == pTemp)
  49.         return NULL;

  50.     memset(pTemp, 0, sizeof(MEMORY_BLOCK_t) + wUnitNum * wUnitSize);

  51.     pstMemoryBlock = (MEMORY_BLOCK_t *)pTemp;
  52.     pstMemoryBlock->wAllUnitSize = (MM_UINT32)(wUnitNum * wUnitSize);
  53.     pstMemoryBlock->wFreeUnitNum = wUnitNum - 1;
  54.     pstMemoryBlock->wFirstUnitID = 1;
  55.     pstMemoryBlock->pstNext = NULL;

  56.     pTemp = pstMemoryBlock->acData;
  57.     for(i = 1; i < wUnitNum; i++)
  58.     {
  59.         *(MM_UINT32 *)pTemp = i;
  60.         pTemp += wUnitSize;
  61.     }

  62.     return pstMemoryBlock;
  63. }

  64. void *MM_AllocMemory(MEMORY_POOL_t *pstMemoryPool, MM_UINT32 wMemSize)
  65. {
  66.     static int iAllocCount = 0;
  67.     void *pRetVal = NULL;
  68.     MM_UCHAR *pTemp = NULL;
  69.     MEMORY_BLOCK_t *pstMemoryBlock = NULL;

  70.     if(NULL == pstMemoryPool )
  71.     {
  72.         fprintf(stderr, "params must is not NULL, [%s, %d]\n", __FILE__, __LINE__);
  73.         return NULL;
  74.     }

  75.     if(wMemSize > pstMemoryPool->wEveryUnitSize)
  76.     {
  77.         fprintf(stderr, "alloc memory size is too large, [%s, %d]\n", __FILE__, __LINE__);
  78.         return NULL;
  79.     }

  80.     pthread_mutex_lock(&pstMemoryPool->stMemPoolLock);

  81.     /* TODO[1]: no memory block, alloc memory block first */
  82.     if(NULL == pstMemoryPool->pstMemoryBlock)
  83.     {
  84.         pstMemoryBlock = MM_AllocMemoryBlock(pstMemoryPool->wInitUnitNum, \
  85.                 pstMemoryPool->wEveryUnitSize);
  86.         if(NULL == pstMemoryBlock)
  87.         {
  88.             fprintf(stderr, "fail to MM_AllocMemoryBlock, [%s, %d]\n", __FILE__, __LINE__);
  89.             pRetVal = NULL;    
  90.             goto MM_AllocMemory_Exit;
  91.         }

  92.         pstMemoryBlock->pstNext = pstMemoryPool->pstMemoryBlock;
  93.         pstMemoryPool->pstMemoryBlock = pstMemoryBlock;

  94.         pRetVal = (void *)pstMemoryBlock->acData;
  95.         goto MM_AllocMemory_Exit;
  96.     }

  97.     /* TODO[2]: try to find exsit memory unit */
  98.     pstMemoryBlock = pstMemoryPool->pstMemoryBlock;
  99.     while(NULL != pstMemoryBlock && 0 == pstMemoryBlock->wFreeUnitNum)
  100.     {
  101.         pstMemoryBlock = pstMemoryBlock->pstNext;
  102.     }

  103.     if(NULL != pstMemoryBlock)
  104.     {
  105.         pTemp = pstMemoryBlock->acData + \
  106.                 (pstMemoryBlock->wFirstUnitID * pstMemoryPool->wEveryUnitSize);    

  107.         pstMemoryBlock->wFirstUnitID = *(MM_UINT32 *)pTemp;    
  108.         pstMemoryBlock->wFreeUnitNum --;

  109.         pRetVal = (void *)pTemp;
  110.         goto MM_AllocMemory_Exit;
  111.     }

  112.     /* TODO[3]: no more memory to alloc, then alloc memory block */        
  113.     pstMemoryBlock = MM_AllocMemoryBlock(pstMemoryPool->wGrowUnitNum, \
  114.             pstMemoryPool->wEveryUnitSize);

  115.     if(NULL == pstMemoryBlock)
  116.     {
  117.         pRetVal = NULL;
  118.         goto MM_AllocMemory_Exit;
  119.     }

  120.     pstMemoryBlock->pstNext = pstMemoryPool->pstMemoryBlock;                
  121.     pstMemoryPool->pstMemoryBlock = pstMemoryBlock;

  122.     pRetVal = (void *)pstMemoryBlock->acData;

  123. MM_AllocMemory_Exit:
  124.     pthread_mutex_unlock(&pstMemoryPool->stMemPoolLock);

  125.     tool_printf("iAllocCount = %d\n", ++iAllocCount);

  126.     return pRetVal;    
  127. }

  128. int MM_FreeMemory(MEMORY_POOL_t *pstMemoryPool, void *pFreeMem)
  129. {
  130.     int iRetVal = 0;
  131.     static int iFreeCount = 0;
  132.     MEMORY_BLOCK_t *pstTemp = NULL;
  133.     MEMORY_BLOCK_t *pstMemoryBlock = NULL;

  134.     if(NULL == pstMemoryPool || NULL == pFreeMem)
  135.         return -1;

  136.     pthread_mutex_lock(&pstMemoryPool->stMemPoolLock);

  137.     pstMemoryBlock = pstMemoryPool->pstMemoryBlock;

  138.     while( (NULL != pstMemoryBlock) && ( \
  139.                 ( (MM_ULONG)pFreeMem < (MM_ULONG)(pstMemoryBlock->acData) ) || \
  140.                  ( (MM_ULONG)pFreeMem >= (MM_ULONG)(pstMemoryBlock->acData + pstMemoryBlock->wAllUnitSize) ) )
  141.          )
  142.     {
  143.         pstMemoryBlock = pstMemoryBlock->pstNext;
  144.     }
  145.     if(NULL == pstMemoryBlock)
  146.     {
  147.         iRetVal = -1;
  148.         goto MM_FreeMemory_Exit;
  149.     }

  150.     /* unit status changed: busy -> free */
  151.     pstMemoryBlock->wFreeUnitNum ++;
  152.     *(MM_UINT32 *)pFreeMem = pstMemoryBlock->wFirstUnitID;
  153.     pstMemoryBlock->wFirstUnitID = (MM_ULONG)( ((MM_ULONG)pFreeMem - \
  154.                 (MM_ULONG)pstMemoryBlock->acData) / pstMemoryPool->wEveryUnitSize );

  155.     /* if all unit memory are free in the block, then free the block */
  156.     if(pstMemoryBlock->wAllUnitSize == pstMemoryBlock->wFreeUnitNum * pstMemoryPool->wEveryUnitSize)
  157.     {
  158.         /* -------- it's the first block -------- */
  159.         if(pstTemp == pstMemoryBlock)
  160.         {
  161.             pstMemoryPool->pstMemoryBlock = pstMemoryBlock->pstNext;
  162.             free(pstMemoryBlock);

  163.             iRetVal = 0;
  164.             goto MM_FreeMemory_Exit;
  165.         }

  166.         /* ------- it's not the first block ----- */
  167.         pstTemp = pstMemoryPool->pstMemoryBlock;

  168.         /* find the prev node */
  169.         while(NULL != pstTemp && pstMemoryBlock != pstTemp->pstNext)
  170.         {
  171.             pstTemp = pstTemp->pstNext;    
  172.         }
  173.         if(NULL != pstTemp)
  174.         {
  175.             /* link prev block and next block */
  176.             pstTemp->pstNext = pstMemoryBlock->pstNext;
  177.             free(pstMemoryBlock);

  178.             iRetVal = 0;
  179.             goto MM_FreeMemory_Exit;
  180.         }
  181.         else
  182.         {
  183.             iRetVal = -1;
  184.             goto MM_FreeMemory_Exit;
  185.         }

  186.         pstMemoryPool->pstMemoryBlock = pstMemoryBlock->pstNext;
  187.     }

  188.     iRetVal = 0;

  189. MM_FreeMemory_Exit:

  190.     pthread_mutex_unlock(&pstMemoryPool->stMemPoolLock);

  191.     tool_printf("iFreeCount = %d\n", ++iFreeCount);

  192.     return iRetVal;
  193. }

  194. #if 0
  195. int main(int argc, const char *argv[])
  196. {
  197.     int i = 0;
  198.     char *pBuf = NULL;
  199.     MEMORY_POOL_t *pstMemoryPool = NULL;    

  200.     /* 4KB/unit, 1K/block, 1K/block */
  201.     pstMemoryPool = MM_CreateMemoryPool(1 << 10, 1 << 10, 1 << 10);

  202.     for(i = 0; i <= 1 << 10; i++)
  203.         pBuf = MM_AllocMemory(pstMemoryPool, 1024);

  204.     /*sprintf(pBuf, "memory pool");*/
  205.     /*printf("pBuf = %s\n", pBuf);*/

  206.     /*MM_FreeMemory(pstMemoryPool, pBuf);    */
  207.     
  208.     return 0;
  209. }
  210. #endif



    
阅读(762) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~