图文结合 带你用纯C实现一个内存池( 二 )


图文结合 带你用纯C实现一个内存池

文章插图
 
大块内存的分配与管理对于大块内存,前面已经说了,用户申请的时候,内存池才申请
申请一块大内存
图文结合 带你用纯C实现一个内存池

文章插图
 
再申请一块大内存
图文结合 带你用纯C实现一个内存池

文章插图
 
内存池代码实现向外提供的api
  • mp_create_pool:创建一个线程池,其核心是创建struct mp_pool_s这个结构体,并申请4k内存,将各个指针指向上文初始状态的图一样 。
  • mp_destroy_pool:销毁内存池,遍历小块结构体和大块结构体,进行free释放内存
  • mp_malloc:提供给用户申请内存的api
  • mp_calloc:通过mp_malloc申请内存后置零,相当于calloc
  • mp_free:释放由mp_malloc返回的内存
  • mp_reset_pool:将block的last置为初始状态,销毁所有大块内存
  • monitor_mp_poll:监控内存池状态
struct mp_pool_s *mp_create_pool(size_t size);void mp_destroy_pool(struct mp_pool_s *pool);void *mp_malloc(struct mp_pool_s *pool, size_t size);void *mp_calloc(struct mp_pool_s *pool, size_t size);void mp_free(struct mp_pool_s *pool, void *p);void mp_reset_pool(struct mp_pool_s *pool);void monitor_mp_poll(struct mp_pool_s *pool, char *tk);相关结构体的定义mp_pool_s 就是整个内存池的管理结构,我们做的内存池是一个连接一个内存池,所以对于整个程序而言,内存池对象是有很多个的 。
可能读者会有疑问,有了head,为什么还有current,是因为如果一个block剩余空间小于size超过一定次数后,将current指向下一个block,这样就加快内存分配效率,减少遍历次数 。
//每4k一block结点struct mp_node_s {unsigned char *end;//块的结尾unsigned char *last;//使用到哪了struct mp_node_s *next;//链表int quote;//引用计数int failed;//失效次数};struct mp_large_s {struct mp_large_s *next;//链表int size;//alloc的大小void *alloc;//大块内存的起始地址};struct mp_pool_s {struct mp_large_s *large;struct mp_node_s *head;struct mp_node_s *current;};内存对齐访问速度是内存对齐的原因之一,另外一个原因是某些平台(arm)不支持未内存对齐的访问
在4k里面划分内存,那么必然有很多地方是不对齐的,所以这里提供两个内存对齐的函数 。那么为什么要内存对齐呢?其一:提高访问速度;其二:某些平台arm不支持未对其的内存访问,会出错 。
#define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1))#define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))创建与销毁内存池创建一个线程池,其核心是创建struct mp_pool_s这个结构体,并申请4k内存,将各个指针指向上文初始状态的图一样 。
销毁内存池,遍历小块结构体和大块结构体,进行free释放内存 。
//创建内存池struct mp_pool_s *mp_create_pool(size_t size) {struct mp_pool_s *pool;if (size < PAGE_SIZE || size % PAGE_SIZE != 0) {size = PAGE_SIZE;}//分配4k以上不用malloc,用posix_memalign/*int posix_memalign (void **memptr, size_t alignment, size_t size);*/int ret = posix_memalign((void **) &pool, MP_ALIGNMENT, size); //4K + mp_pool_sif (ret) {return NULL;}pool->large = NULL;pool->current = pool->head = (unsigned char *) pool + sizeof(struct mp_pool_s);pool->head->last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);pool->head->end = (unsigned char *) pool + PAGE_SIZE;pool->head->failed = 0;return pool;}//销毁内存池void mp_destroy_pool(struct mp_pool_s *pool) {struct mp_large_s *large;for (large = pool->large; large; large = large->next) {if (large->alloc) {free(large->alloc);}}struct mp_node_s *cur, *next;cur = pool->head->next;while (cur) {next = cur->next;free(cur);cur = next;}free(pool);}
图文结合 带你用纯C实现一个内存池


推荐阅读