重复造轮子系列--内存池(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 }