重复造轮子系列--内存池(C语言)

这个代码是我上个公司工作项目的里面内存管理(基于伙伴算法)的一个简化又简化的版本。

因为没有内存边界检查;

因为没有内存使用统计;

因为没有考虑线程安全;

因为没有内存分配操作的具体文件位置信息;

因为没有考虑内存的浪费;

因为特别简单。。。所以也有一些用处,我定义了最小的内存为8字节,因此可以将任意内存大小散列到8的倍数之内,对于64位的通信系统来说,字节对齐是非常重要的;

 

mem_pool.h

 1 #ifndef MEM_POOL_H_
 2 #define MEM_POOL_H_
 3 
 4 typedef struct MemBlock {
 5     struct MemBlock* next;
 6     int size;
 7     void *ptr;
 8 } MemBlock;
 9 
10 typedef unsigned char byte;
11 
12 // 8 16 32 64 128 256 512 1024 2048 4096 
13 // 1 2  4  8  16  32  64  128  256  512
14 // 0 1  2  3  4   5   6   7    8    9
15 
16 #define MEM_POOL_MAX 10
17 #define MEM_BLOCK 8
18 #define MEM_BLOCK_BASE 8192
19 #define MEM_BLOCK_TYPE_NUM 10
20 #define MEM_BLOCK_FREE -1
21 
22 int       mem_pool_index(size_t size);
23 void      mem_pool_init();
24 void      mem_pool_free();
25 int       mem_block_num(size_t size);
26 MemBlock* mem_block_head_get(size_t size);
27 void*     mem_get(size_t size);
28 int       mem_free(void **ptr);
29 
30 #define mem_ret(ptr) mem_free((void **)&ptr)
31 
32 //////////////////////////////////////////////////////////////////////////
33 
34 typedef struct MemBlockDlist {
35     struct MemBlockDlist* prev;
36     struct MemBlockDlist* next;
37     int size;
38     void *ptr;
39 } MemBlockDlist;
40 
41 void  mem_pool_dlist_init();
42 void  mem_pool_dlist_free();
43 void* mem_realloc(size_t size);
44 void  mem_release(void** ptr);
45 
46 #define mem_alloc(s) mem_realloc(s)
47 #define mem_relex(p) mem_release((void **)&p)
48 
49 #endif

mem_pool.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <math.h>
  4 #include "mem_pool.h"
  5 
  6 static byte*     g_pool_mem[MEM_POOL_MAX] = {0};
  7 static MemBlock* g_pool[MEM_POOL_MAX]     = {0};
  8 const float log2 = log(2.0);
  9 int mem_pool_index(size_t size) {
 10     if (size > 0 && size <= MEM_BLOCK) return 0;
 11 
 12     size_t s = 1;
 13     size_t t = size;
 14     size_t i;
 15 
 16     i = log((float)t)/log2; 
17
s = s<<i; 18 return s == size ? i-3 : i-2; 19 } 20 21 MemBlock* mem_block_head(size_t index) { 22 if (index < 0 || index >= MEM_POOL_MAX) 23 return NULL; 24 25 return g_pool[index]; 26 } 27 28 MemBlock* mem_block_head_get(size_t size) { 29 if (size > MEM_BLOCK_BASE/2 || size <= 0) { 30 printf("size=%d too big to mem pool. using malloc plz\n", size); 31 return NULL; 32 } 33 return mem_block_head(mem_pool_index(size)); 34 } 35 36 int mem_block_num(size_t size) { 37 return MEM_BLOCK_BASE/size;// size > 0 is true 38 } 39 40 static MemBlock* mem_block_alloc(byte* buf, int block_size, int block_num) { 41 MemBlock *head, *curr, *next; 42 int i; 43 44 head = (MemBlock *)buf; 45 head->size = MEM_BLOCK_FREE; 46 head->ptr = (byte*)head + sizeof(MemBlock); 47 head->next = NULL; 48 49 curr = head; 50 for (i=1; i<block_num; i++) { 51 next = (MemBlock*)((byte*)curr + block_size); 52 next->size = MEM_BLOCK_FREE; 53 next->ptr = (byte*)next + sizeof(MemBlock); 54 curr->next = next; 55 next->next = NULL; 56 curr = next; 57 } 58 return head; 59 } 60 61 void mem_pool_init() { 62 size_t l, i, s, n, b; 63 for (l=0; l<MEM_BLOCK_TYPE_NUM; l++) { 64 i = 1 << l; 65 b = i * MEM_BLOCK; 66 s = b + sizeof(MemBlock); 67 n = mem_block_num(b); 68 69 g_pool_mem[l] = (byte *)malloc(s * n); 70 if (NULL == g_pool_mem[l]) { 71 break; 72 } 73 g_pool[l] = mem_block_alloc(g_pool_mem[l], s, n); 74 } 75 return; 76 } 77 78 void mem_pool_free() { 79 for (int i=0; i<MEM_BLOCK_TYPE_NUM; i++) { 80 if (NULL != g_pool_mem[i]) { 81 free(g_pool_mem[i]); 82 g_pool_mem[i] = NULL; 83 g_pool[i] = NULL; 84 } 85 } 86 return; 87 } 88 89 void* mem_get(size_t size) { 90 MemBlock* head = mem_block_head_get(size); 91 if (NULL == head) return NULL; 92 93 do { 94 if (head->size == MEM_BLOCK_FREE) { 95 head->size = size; 96 return head->ptr; 97 } else { 98 head = head->next; 99 } 100 } while (head->next); 101 102 return NULL; 103 } 104 105 int mem_free(void **ptr) { 106 if (NULL == ptr || NULL == *ptr) return 0; 107 108 MemBlock *block = (MemBlock *)((byte*)(*ptr) - sizeof(MemBlock)); 109 block->size = MEM_BLOCK_FREE; 110 111 return 1; 112 }

mem_pool_dlist.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <math.h>
  5 #include "mem_pool.h"
  6 
  7 static byte*          g_pool_buff[MEM_POOL_MAX]     = {0};
  8 static MemBlockDlist* g_pool_objects[MEM_POOL_MAX]  = {0};
  9 static MemBlockDlist* g_pool_freelist[MEM_POOL_MAX] = {0};
 10 static MemBlockDlist* g_pool_cursor[MEM_POOL_MAX]   = {0};
 11 
 12 MemBlockDlist* mem_block_dlist_head(size_t index) {
 13     if (index < 0 || index >= MEM_POOL_MAX) 
 14         return NULL;
 15 
 16     return g_pool_objects[index];
 17 }
 18 
 19 void mem_pool_cursor_init() {
 20     for(size_t i=0; i<MEM_POOL_MAX; i++)
 21         g_pool_cursor[i] = mem_block_dlist_head(i);
 22 }
 23 
 24 static MemBlockDlist* mem_block_dlist_alloc(byte* buf, int bk_size, int bk_num){
 25     MemBlockDlist *head, *curr, *next;
 26     int i;
 27 
 28     head = (MemBlockDlist *)buf;
 29     head->size = MEM_BLOCK_FREE;
 30     head->ptr  = (byte*)head + sizeof(MemBlockDlist);
 31     head->prev = NULL;
 32     head->next = NULL;
 33 
 34     curr = head;
 35     for (i=1; i<bk_num; i++) {
 36         next = (MemBlockDlist*)((byte*)curr + bk_size);
 37         next->size = MEM_BLOCK_FREE;
 38         next->ptr  = (byte*)next + sizeof(MemBlockDlist);
 39 
 40         curr->next = next;
 41         next->prev = curr;
 42         next->next = NULL;
 43 
 44         curr = next;
 45     }
 46     return head;
 47 }
 48 
 49 void mem_pool_dlist_init() {
 50     size_t l, i, s, n, b;
 51     for (l=0; l<MEM_BLOCK_TYPE_NUM; l++) {
 52         i = 1 << l;
 53         b = i * MEM_BLOCK;
 54         s = b + sizeof(MemBlockDlist);
 55         n = mem_block_num(b);
 56 
 57         g_pool_buff[l] = (byte *)malloc(s * n);
 58         if (NULL == g_pool_buff[l]) {
 59             break;
 60         }
 61         g_pool_objects[l] = mem_block_dlist_alloc(g_pool_buff[l], s, n);
 62     }
 63 
 64     mem_pool_cursor_init();
 65 }
 66 
 67 void mem_pool_dlist_free() {
 68     for (int i=0; i<MEM_BLOCK_TYPE_NUM; i++) {
 69         if (NULL != g_pool_buff[i]) {
 70             free(g_pool_buff[i]);
 71 
 72             g_pool_buff[i]     = NULL;
 73             g_pool_objects[i]  = NULL;
 74             g_pool_freelist[i] = NULL;
 75             g_pool_cursor[i]   = NULL;
 76         }
 77     }
 78 }
 79 
 80 MemBlockDlist* mem_free_block_get(int index) {
 81     if (index < 0 || index >= MEM_POOL_MAX) return NULL;
 82 
 83     MemBlockDlist* tmp = g_pool_freelist[index];
 84     if (!tmp) return NULL;
 85 
 86     g_pool_freelist[index] = tmp->next;
 87     g_pool_freelist[index]->prev = NULL;
 88     tmp->next = NULL;
 89 
 90     return tmp;
 91 }
 92 
 93 void* mem_realloc(size_t size) {
 94     int index = mem_pool_index(size);
 95     if (index < 0 || index >= MEM_POOL_MAX) 
 96         return NULL;
 97     
 98     MemBlockDlist* ptr = mem_free_block_get(index);
 99     if (ptr) {
100         ptr->size = size;
101         return ptr->ptr;
102     }
103 
104     MemBlockDlist* cursor = g_pool_cursor[index];
105     if (NULL == cursor) {
106         printf("pool index=%d memory leak or queue is all used.\n", index);
107         return NULL;
108     }
109     
110     if (MEM_BLOCK_FREE == cursor->size) {
111         g_pool_cursor[index] = cursor->next;
112         cursor->size = size;
113         return cursor->ptr;
114     }
115 
116     return NULL;
117 }
118 
119 void  mem_release(void** ptr) {
120     if (NULL == ptr || NULL == *ptr) 
121         return;
122 
123     size_t len = sizeof(MemBlockDlist);
124     MemBlockDlist *block = (MemBlockDlist *)((byte*)(*ptr) - len);
125 
126     int index = mem_pool_index(block->size);
127     if (index < 0 || index >= MEM_POOL_MAX) 
128         return;
129 
130     memset((byte*)(*ptr), 0, block->size);
131     MemBlockDlist* top = g_pool_freelist[index];
132 
133     g_pool_freelist[index] = block;
134     if (top) {    
135         g_pool_freelist[index]->next = top;
136     }
137 
138     g_pool_freelist[index]->size = MEM_BLOCK_FREE;
139 }

 

posted @ 2017-02-06 13:26  丹西  阅读(1400)  评论(0编辑  收藏  举报