1.设计原理
1.内存池实际就是预先分配不同大小的内存块, 然如果需要调用的时候, 直接把这个块的指针返回.
图中, 就是内存池划分.
2.通过一个链表, 将这些分配的内存块串联起来, 每一块最头部都记录这这个块的信息
3.分配的时候, 会遍历一遍链表, 找到is_used未被置1, pool_size大于或等于分配的大小的内存块(并且这个pool_size必定是内存池最小的那块), 如果找到, 则is_used被置1. 同时返回那个内存块的数据存储的首位置addr + sizeof(pool_t);.
4. 释放则是遍历每个内存块, 比较内存块加上一个pool_t的大小(if (pt + sizeof(pool_t) == p)), 是否和释放的指针相等
2.源码
2.1 头文件
#ifndef POOL_H
#define POOL_H
typedef struct pool{unsigned int pool_size;unsigned char is_used;struct pool *next;
}pool_t;
int init_pool(int arg_num, ...);
void* pool_malloc(unsigned int size);
unsigned char pool_free(void* p);#endif
2.2 C文件
#include "pool.h"
#include <stdarg.h>
#include <stdlib.h>
#include "./UART/uart.h"/*我们要进入启动文件, 调整一下堆区大小*/static pool_t pool_head = {0};int init_pool(int arg_num, ...)
{unsigned char i, j;unsigned int pool_size, pool_num;pool_t *new_pool, * p;p = &pool_head;va_list ap;va_start(ap, arg_num);for (i = 0; i < arg_num / 2; i++){pool_size = va_arg(ap, int);pool_num = va_arg(ap, int);for (j = 0; j < pool_num; j++){new_pool = (pool_t*)malloc(pool_size + sizeof(pool_t));if (new_pool == NULL){return 0;}new_pool->next = p->next;p->next = new_pool;new_pool->is_used = 0;new_pool->pool_size = pool_size;p = &pool_head;}}va_end(ap);return 1;
}void* pool_malloc(unsigned int size)
{pool_t* p = pool_head.next;pool_t* addr = &pool_head, *temp;while (p) {if (p->is_used == 0 && p->pool_size >= size){temp = p;if (addr == &pool_head){addr = temp;}else {if (addr->pool_size > temp->pool_size) {addr = temp;}}}p = p->next;}if (addr == &pool_head){printf("malloc failed\r\n");return 0;}addr->is_used = 1;return addr + sizeof(pool_t);
}unsigned char pool_free(void* p)
{unsigned char free_succes = 0;pool_t* pt = pool_head.next;while (pt){if (pt + sizeof(pool_t) == p) {free_succes = 1;break;}pt = pt->next;}pt->is_used = 0;return free_succes;
}
2.3 函数介绍
内存池初始化:
int init_pool(int arg_num, ...);
初始时一个不定长参数函数, 初始化的时候注意, init_pool(6, 200, 2, 300, 2, 400, 2);第一个参数是后面不定长参数的个数, 第二个参数是分配一个200字节大小的块, 第三个参数是分配200字节块的个数, 依次类推, 但是也要注意不用分配太大,.
注意: 这些都是没在实际项目中使用的, 还没接受过项目的考验, 但是理论上来讲, 如果是裸机代码从运行来看可以直接拿来用, 如果跑RTOS, 我还不能保证, 可能释放和分配要加互斥锁, 防止访问上造成冲突, 或者直接挂起任务调度, 或者进入临界区.如果有兄弟拿到项目, 发现问题,请评论下,我进行修改.
2.4 测试
void main()
{int*p,*p1, *p2, *p3, *p4, *p5, *p6, *p7;init_pool(6, 200, 2, 300, 2, 400, 2);printf("sizeof(pool_t) = %d", sizeof(pool_t));p = (int*)pool_malloc(100);p1 = (int*)pool_malloc(100);p2 = (int*)pool_malloc(100);p3 = (int*)pool_malloc(100);p4 = (int*)pool_malloc(100);*p4 = 555;p5 = (int*)pool_malloc(100);p6 = (int*)pool_malloc(100);pool_free(p5);p7 = (int*)pool_malloc(100);while (1);
}