一个简单的内存池实现的例子

 前几篇文章对内存池做了两次改进和简化,因为在liunux上内存分配的malloc已经在系统的优化控制范围内了,所以一定范围内的内存分配还是交由系 统比较快,经测试基本上对于大于256字节的内存分配交由本内存池分配性能有明显提高,本次系统所有其他的对象都是构建在这个内存池之上,内存池会对用户 申请的内存作出二次归类管理
代码如下:

memeory.h

/* 
* File:   memorys.h:内存池管理系统
* Author: netpet
* Flower net server
*重要:实际的控制范围是最小值MinIndex*Align,最大值是(InitMemPool+MinIndex-2)*Align
* 本程序是为一体化web server产品专用设计,具有部分代码为具体产品优化而不代表普遍通用性的特性
* 程序在linux 2.46下调试通过,编辑工具netbeans 6.1 for c
*该结构用一个自增长的链表结构体保存分链表,每个结构体中包含具体链表的头部、尾部和空闲分界线指针,维护一个链表
*大致结构如下:
*            MemPool
*     V       V      V      ...
*   链表1   链表2   链表3   ...
*通过这样一个结构系统就可以灵活增加减少系统池,并且可以控制池内结构,控制总数据量
* 联系方式:Email:[email protected] QQ:51977431
* Created on 2008年5月26日, 下午4:18
*/

#ifndef _MEMORYS_H
#define    _MEMORYS_H

#ifdef    __cplusplus
extern "C" {
#endif

#define InitMemPool 1000 //初始化池所能拥有的数量,不能超过255*255
#define new(type) ((type *)(New(sizeof(type))))
#define sizes sizeof(MemPool)

    extern long MaxMemory;
    extern int Align;
    extern int InitMemItem;
    extern int ExpendMemItem;
    extern int MinBlock;
    extern long MaxBlock;
    extern int MinIndex;

    typedef struct _MemItem {
        struct _MemItem *next;
    } MemItem;

    /*
     *该结构体是linux 2.4.6状态下malloc申请内存时强加的协议头结构,用来记录实际内存大小
     */
    struct mem_block {
        int is_available; //这是一个标记
        int size; //这是实际空间的大小
    };

    /*池集合*/
    typedef struct _MemPool {
        int name; //名称,同item_size,不管什么类型,申请的同一大小内存快放在同一个内存管理区域,视为同一名称,
        long max_memory; //最多占用的内存
        int init_item; //初始化多少item
        int per_expend_item; //每次扩展时一次申请多少项
        int current_item; //当前有多少项被使用
        int total_item; //共有多少项
        MemItem * first; //IO池头地址
        MemItem * last; //IO池最后一项的地址
        MemItem * current; //IO池分割空闲和使用中的分割地址
    } MemPool;

    /**
     *取会给定结构的池结构体
     */
    extern void InitPool(void); /*初始化池*/
    extern void FreePool(); /*释放池*/


    extern void InitItem(unsigned int name); //初始化具体项的链表
    extern void *New(unsigned int size); //初始化具体项的链表
    extern void ExpendItem(unsigned int name); //初始化扩展项的链表
    extern void Free(void *myp); //释放具体一项
    extern void PrintPool(void);

#ifdef    __cplusplus
}
#endif

#endif    /* _MEMORYS_H */

memorys.c

/* 
* File:   memorys.c:内存池管理系统
* Author: netpet
* Flower net server
*重要:实际的控制范围是最小值MinIndex*Align,最大值是(InitMemPool+MinIndex-2)*Align
* 本程序是为一体化web server产品专用设计,具有部分代码为具体产品优化而不代表普遍通用性的特性
* 程序在linux 2.46下调试通过,编辑工具netbeans 6.1 for c
*该结构用一个自增长的链表结构体保存分链表,每个结构体中包含具体链表的头部、尾部和空闲分界线指针,维护一个链表
*大致结构如下:
*            MemPool
*     V       V      V      ...
*   链表1   链表2   链表3   ...
*通过这样一个结构系统就可以灵活增加减少系统池,并且可以控制池内结构,控制总数据量
* 联系方式:Email:[email protected] QQ:51977431
* Created on 2008年5月26日, 下午4:18
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
#include "memorys.h"
#include "log.h"
#include "config.h"

//内存池锁,现在还不确定是多锁性能更好还是总锁的性能好
pthread_mutex_t Memlock;
//内存池管理的项数范围,管理的最小为MinBlock,最大为InitMemPool*Align+MinBlock,除此之外的均交由malloc free自行管理
MemPool poolIndex[InitMemPool];
//Lock memLock;
static long totalByte;
//最大内存
long MaxMemory;
int Align;
int InitMemItem;
int ExpendMemItem;
int MinBlock;
long MaxBlock;
int MinIndex;

/*初始化池*/
void InitPool(void) {

    MaxMemory = config->memory.MaxMemory;
    MinIndex = config->memory.MinIndex;
    Align = config->memory.Align;
    InitMemItem = config->memory.InitMemItem;
    ExpendMemItem = config->memory.ExpendMemItem;
    MinBlock = Align*(MinIndex+1);
    MaxBlock = (InitMemPool+MinIndex)*Align;


    pthread_mutex_init(&Memlock, NULL);
    int i;
    MemPool *p;
    for (i = 0; i < InitMemPool; i++) {
        p = &poolIndex[i];
        /*基本链表设置*/
        p->name = i + MinIndex;
        p->first = NULL;
        p->last = NULL;
        p->current = NULL;
        /*设置杂项*/
        p->max_memory = 0;
        p->init_item = 0;
        p->per_expend_item = 0;
        p->current_item = 0;
        p->total_item = 0;
    }
    printf("内存池初始化成功!/n");
}
/*
*释放内存池
*/
void FreePool() {
pthread_mutex_lock(&Memlock);
    MemPool *pool;
    int i;
    for (i = 0; i < InitMemPool; i++) {
        pool = &poolIndex[i];
        if (pool->first != NULL) {
             if (pool->total_item > 0) {
                MemItem * mi = pool->first;
                MemItem *ls;
                while (mi != NULL) {
                    ls=mi;
                    mi = mi->next;
                    free(ls);
                   
                }
            }
        }
    }
     pthread_mutex_unlock(&Memlock);
     pthread_mutex_destroy(&Memlock);
     printf("Flower系统内存释放完毕!/n");
}

/*初始化项*/
void InitItem(unsigned int name) {
    
    int blk;
    MemItem *ip; /*项的链表指针*/
    /*构造容器*/
    MemPool *p = &poolIndex[name - MinIndex];

    (p->total_item) += ((p->init_item) == 0 ? InitMemItem : (p->init_item));
    p->first = (MemItem *) malloc(name * Align); /*创建第一个块*/

    ip = p->first;
    for (blk = 1; blk < (p->init_item == 0 ? InitMemItem : p->init_item); ++blk) {
        ip->next = (MemItem *) malloc(name * Align);
        ip = ip->next;
    }
    ip->next = NULL;
    p->last = ip;
    totalByte += name * Align * (p->init_item == 0 ? InitMemItem : p->init_item);

}

/*扩展当前池项的下属内存块*/
void ExpendItem(unsigned int name) {
    int blk;
    MemItem *ip; /*项的链表指针*/
    /*构造容器*/

    MemPool *p = &poolIndex[name - MinIndex];

    p->total_item += (p->per_expend_item == 0 ? ExpendMemItem : p->per_expend_item);
    p->last->next = (MemItem *) malloc(name * Align); /*创建第一个块*/
    ip = p->last->next;
    for (blk = 1; blk < (p->per_expend_item == 0 ? ExpendMemItem : p->per_expend_item); ++blk) {
        ip->next = (MemItem *) malloc(name * Align);
        ip = ip->next;
    }
    ip->next = NULL;
    p->last = ip;
    totalByte += name * Align * (p->per_expend_item == 0 ? ExpendMemItem : p->per_expend_item);
}

/*
*申请新的内存块
*/
void *New(unsigned int size) {
    //MemItem *ip;/*项的链表指针*/
    /*构造容器*/
    if (totalByte > MaxMemory)
        return NULL; //申请的总内存过大,请调大默认最大内存设置或者检察内寻泄露
    size = (size + Align - 1) &~ (Align - 1);
    if (size >= MaxBlock || size < MinBlock) {
        return malloc(size);
    }
    size = size / Align;
    MemPool *p = &poolIndex[size - MinIndex];

    if (p->first == NULL)
        InitItem(size);
    if (p->first == NULL)
        Error("当前项初始化时发生了错误,可能原因为系统内存不足%p", p);

    //防止检测初始化不成功导致的意外错误
    assert(p->first);
    pthread_mutex_lock(&Memlock);
    if (p->first->next == NULL) {
        ExpendItem(size);
        //防止检测扩展项不成功导致的错误
        if (p->first->next == NULL)
            Error("当前项扩展时发生了错误,可能会导致内存池New死锁,可能原因为系统内存不足%p", p->first);
    }

    MemItem *ips;
    ips = p->first;
    p->first = p->first->next;
    p->current_item++;
    pthread_mutex_unlock(&Memlock);
    return ips; /*此处返回的是向后偏移过的指针*/
}

/*
*释放内存块
*/
void Free(void *myp) {

    struct mem_block * realsize = (struct mem_block *) myp; //转化为Short指针
    --realsize; /*向前移动short位移*/
    int size = realsize->size - 9;
    ++realsize;

    if (size >= MaxBlock || size < MinBlock) {
        free(realsize);
        return;
    }
    size = ((size + Align - 1) &~ (Align - 1)) / Align;
    MemItem *ip = (MemItem *) realsize; /*转化回来*/
    MemPool *p = &poolIndex[size - MinIndex];

    if (p == NULL) {
        Error("试图释放一个不属于池的指针,直接释放了,当前size%d/n", size);
        return;
    }
    pthread_mutex_lock(&Memlock);
    if (p->first != NULL) {

        ip->next = NULL;
        p->last->next = ip;
        p->last = p->last->next;
        p->current_item--;

    } else {
        Error("产生了一个野指针,,当前size:%d", size);
    }
    pthread_mutex_unlock(&Memlock);
    return;
}

/*
*输出内存池管理的内存
*/
void PrintPool(void) {
    MemPool *pool;
    int i;
    for (i = 0; i < InitMemPool; i++) {
        pool = &poolIndex[i];
        if (pool->first != NULL) {
            printf("/n名称%i 共有%i 使用%i,初始化:%i 当前地址%p/n", pool->name, pool->total_item, pool->current_item, pool->init_item, pool->current);
            if (pool->total_item > 0) {
                MemItem * mi = pool->first;
                while (mi != NULL) {
                    printf("--/t%p", mi);
                    mi = mi->next;
                }
            }
        }

    }
}

你可能感兴趣的:(一个简单的内存池实现的例子)