文章插图
大块内存的分配与管理对于大块内存,前面已经说了,用户申请的时候,内存池才申请
申请一块大内存
文章插图
再申请一块大内存
文章插图
内存池代码实现向外提供的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);}
推荐阅读
- 带你搞懂符号执行的前世今生与最近技术
- 跑路鸟为什么被称作“沙漠地带的小丑”
- 带状疱疹会传染怎么办 带状疱疹会传染吗
- 没带身份证还能坐火车吗 没有身份证可以坐高铁吗
- iOS|iOS15.6带来新功能:和苹果家庭“垃圾邀请”说拜拜
- 乙肝病毒携带者是怎么传播的 乙肝病毒携带者会传染吗
- 翡翠|翡翠与二次元的结合,唤起一代人的记忆……
- 火车带酒规定2019 火车上可以带多少白酒 火车上能带酒吗
- 吐出痰像烂肉带血怎么办
- 骑自行车健身的误区有哪些? 骑自行车锻炼带来的三大效应