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);
} 
                


















