|
楼主 |
发表于 2013-5-8 18:28:13
|
显示全部楼层
本帖最后由 goodlook 于 2013-5-8 23:39 编辑
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#define TRUE 1
#define FALSE 0
#define OK 0
#define NOK 1
#define BUSY 1
#define SPARE 0
#define _D_RETURN_IF_MALLOC_ERR(p, errno) if(NULL == p){return errno;}
#define MEM_BLK_SIZE 16
/* 内存节点属性结构体 */
typedef struct tagS_MEMORY_NODE
{
size_t ulBlockIndex;
/* 内存块序号 */
size_t ulNumUserBlock;
/* 用户指定的内存块个数 */
struct tagS_MEMORY_NODE *pstNext;/* 下一个节点指针 */
}S_NODE_ATTRIB;
static void *g_pMemory = NULL;
/* 内存池首地址 */
static size_t g_ulNumTotalBlock = 0;
/* 内存池的内存块个数 */
static int *g_pBlockFlag = NULL;
/* 内存池的内存块有效标志 */
static S_NODE_ATTRIB *g_pstAttribNodeHead = NULL;
/* 内存节点属性链表头 */
/*********************************************************************
函 数 名 : k_malloc_setnull
功能描述 : 分配堆空间,并将所分配的空间置0
输入参数 : k_size 欲分配的堆空间大小
输出参数 :
返 回 值 : void*
********************************************************************/
void *k_malloc_setnull(size_t k_size)
{
void *p = malloc(k_size);
_D_RETURN_IF_MALLOC_ERR(p, NULL);
memset((char *)p, 0, k_size);
return p;
}
/*********************************************************************
函 数 名 : addOneNodeToList
功能描述 : 单链表操作,在尾部加入一个节点
输入参数 : ppstNodeHead 链表头部指针的地址(链表头部指针由调用者定义)
pstNodeToInset 欲插入的节点指针
输出参数 : ppstNodeHead 链表头部指针的地址(链表头部指针由调用者定义)
返 回 值 : int
********************************************************************/
int addOneNodeToList(S_NODE_ATTRIB **ppstNodeHead, S_NODE_ATTRIB *pstNodeToInset)
{
S_NODE_ATTRIB *pstNodePrev = NULL;
S_NODE_ATTRIB *pstNodeCur = *ppstNodeHead;
//没有一个节点
if (NULL == *ppstNodeHead)
{
*ppstNodeHead = pstNodeToInset;
}
else
{
//已有节点,插入末尾
while (NULL != pstNodeCur)
{
pstNodePrev = pstNodeCur;
pstNodeCur = pstNodeCur->pstNext;
}
pstNodePrev->pstNext = pstNodeToInset;
}
return 0;
}
static size_t memGetNumTotalBlock(void)
{
return g_ulNumTotalBlock;
}
static void memSetNumTotalBlock(size_t ulNumTotalBlock)
{
g_ulNumTotalBlock = ulNumTotalBlock;
printf("g_ulNumTotalBlock = %d\n", g_ulNumTotalBlock);
return;
}
static void memSetBlockFlag(size_t ulStart, size_t ulLen, int lValue)
{
size_t i = 0;
for (i = 0; i < ulLen; ++i)
{
*(g_pBlockFlag + ulStart + i) = lValue;
}
return;
}
static void memClearBlockFlag(size_t ulBlockIndex, size_t ulNumBlock)
{
memSetBlockFlag(ulBlockIndex, ulNumBlock, FALSE);
return;
}
static void *memGetMemoryStartAddress(void)
{
return g_pMemory;
}
static int memMallocMemory(size_t ulSize)
{
size_t ulNumTotalBlock = 0;
g_pMemory = (void *)k_malloc_setnull(ulSize);
_D_RETURN_IF_MALLOC_ERR(g_pMemory, NOK);
/* 分配内存块标志的空间 */
ulNumTotalBlock = ulSize / MEM_BLK_SIZE;
memSetNumTotalBlock(ulNumTotalBlock);
g_pBlockFlag = (int *)k_malloc_setnull(ulNumTotalBlock * sizeof(int));
_D_RETURN_IF_MALLOC_ERR(g_pBlockFlag, NOK);
return OK;
}
static void memFreeMallocedMemory(void)
{
if (NULL != g_pMemory)
{
free(g_pMemory);
g_pMemory = NULL;
}
memClearBlockFlag(0, memGetNumTotalBlock());
return;
}
/*********************************************************************
函 数 名 : static int memFindAddrAndFreeMemory(size_t ulAddr)
功能描述 : 单链表操作,删除一个节点
输入参数 :
输出参数 :
返 回 值 : int
********************************************************************/
static int memFindAddrAndFreeMemory(size_t ulAddr)
{
S_NODE_ATTRIB *pstNodeCur = g_pstAttribNodeHead;
S_NODE_ATTRIB *pstNodePrev = NULL;
size_t ulAddrRecorded = 0;
for (pstNodeCur = g_pstAttribNodeHead; NULL != pstNodeCur;
(pstNodePrev = pstNodeCur, pstNodeCur = pstNodeCur->pstNext))
{
ulAddrRecorded = (size_t)memGetMemoryStartAddress()
+ MEM_BLK_SIZE * pstNodeCur->ulBlockIndex;
if (ulAddr == ulAddrRecorded)
{
memClearBlockFlag(pstNodeCur->ulBlockIndex, pstNodeCur->ulNumUserBlock);
/* 链表头 */
if (pstNodeCur == g_pstAttribNodeHead)
{
g_pstAttribNodeHead = pstNodeCur->pstNext;
}
/* 尾巴和中间 */
else
{
pstNodePrev->pstNext = pstNodeCur->pstNext;
}
free(pstNodeCur);
return OK;
}
}
return NOK;
}
static int memGetStartIndexOfBlocks(size_t ulNumBlock, size_t *pulIndex)
{
size_t i = 0;
size_t ulNumResult = 0;
size_t ulNumResultTmp = 0;
size_t ulNumTotalBlock = 0;
if (NULL == g_pBlockFlag)
{
printf("g_pMemoryFlag is NULL...\n");
return NOK;
}
ulNumTotalBlock = memGetNumTotalBlock();
for (i = 0; i < ulNumTotalBlock; ++i)
{
if (SPARE == *(g_pBlockFlag + i))
{
ulNumResult++;
}
else
{
ulNumResultTmp = ulNumResult > ulNumResultTmp ? ulNumResult : ulNumResultTmp;
if (ulNumBlock <= ulNumResultTmp)
{
printf("line %d: address index of Block = %d\n", __LINE__, i - ulNumResultTmp);
*pulIndex = i - ulNumResultTmp;
return OK;
}
ulNumResult = 0;
}
}
ulNumResultTmp = ulNumResult > ulNumResultTmp ? ulNumResult : ulNumResultTmp;
if (ulNumBlock <= ulNumResultTmp)
{
printf("line %d: address index of Block = %d\n", __LINE__, i - ulNumResultTmp);
*pulIndex = i - ulNumResultTmp;
return OK;
}
return NOK;
}
void debug_print_flag(void)
{
size_t i = 0;
size_t ulNum = memGetNumTotalBlock();
static size_t ulCount = 0;
printf("check memory flag===%d===\n", ulCount++);
for (i = 0; i < ulNum; ++i)
{
printf("%d ", *(g_pBlockFlag + i));
}
printf("\n");
return;
}
/****************************************************************
Description : 检查欲分配的内存大小
Prototype : static int memCheckMemSize(size_t ulMemSize)
Parameters : size_t ulMemSize - 欲分配的内存池大小(单位Byte)
大小为MEM_BLK_SIZE的整数倍
Return Value : int - 成功返回OK
失败返回NOK
*****************************************************************/
static int memCheckMemSize(size_t ulMemSize)
{
if (0 == ulMemSize
|| ulMemSize % MEM_BLK_SIZE)
{
return NOK;
}
return OK;
}
/****************************************************************
Description : 初始化内存池
Prototype : void* InitMemPool(size_t mem_pool_size)
Parameters : size_t mem_pool_size - 初始的内存池大小(单位Byte)
Return Value : void* - 成功返回内存池首地址
失败返回NULL
*****************************************************************/
void* InitMemPool(size_t mem_pool_size)
{
/* 检查内存大小是否合法 */
if (OK != memCheckMemSize(mem_pool_size))
{
return NULL;
}
/* 分配内存池及其标志空间 */
if (OK != memMallocMemory(mem_pool_size))
{
return NULL;
}
return memGetMemoryStartAddress();
}
/******************************************************************
Description : 销毁内存池
Prototype : void DestroyMemPool(void)
Parameters : 无
Return Value : void
*******************************************************************/
void DestroyMemPool(void)
{
/* 释放已分配的内存池及其标志空间 */
memFreeMallocedMemory();
/* 清0内存池的内存块个数 */
memSetNumTotalBlock(0);
/* 释放内存节点属性链表 */
//freeAllNode();
return;
}
/******************************************************************
Description : 申请内存
Prototype : void* MemAlloc(size_t user_blk_size)
Parameters : size_t user_blk_size – 申请的内存大小(单位byte)
Return Value : void* - 成功则返回可使用的内存区域地址
失败返回NULL
*******************************************************************/
void* MemAlloc(size_t user_blk_size)
{
size_t ulNumUserBlock = user_blk_size / MEM_BLK_SIZE;
size_t total_m = memGetNumTotalBlock();
S_NODE_ATTRIB *pstNodeTmp = NULL;
void *pMemory = NULL;
size_t ulBlockIndex = 0;
printf("ulNumUserBlock = %d\n", ulNumUserBlock);
if (OK != memGetStartIndexOfBlocks(ulNumUserBlock, &ulBlockIndex))
{
printf("space NOT enough...\n");
return NULL;
}
memSetBlockFlag(ulBlockIndex, ulNumUserBlock, TRUE);
pMemory = (void *)((char *)memGetMemoryStartAddress() + MEM_BLK_SIZE * ulBlockIndex);
/* 填充数据 */
pstNodeTmp = (S_NODE_ATTRIB *)k_malloc_setnull(sizeof(S_NODE_ATTRIB));
_D_RETURN_IF_MALLOC_ERR(pstNodeTmp, NULL);
/* 填充数据 */
pstNodeTmp->ulNumUserBlock = ulNumUserBlock;
pstNodeTmp->ulBlockIndex = ulBlockIndex;
/* 将新增节点加入链表 */
addOneNodeToList(&g_pstAttribNodeHead, pstNodeTmp);
debug_print_flag();
printf("mem_addr = [%p]\n", pMemory);
return pMemory;
}
/******************************************************************
Description : 释放内存
Prototype : int MemFree(void* mem_addr)
Parameters : void* mem_addr - 要释放的内存地址
Return Value : int - 成功返回0
失败返回-1
*******************************************************************/
int MemFree(void* mem_addr)
{
if (NULL == mem_addr)
{
return -1;
}
if (OK != memFindAddrAndFreeMemory((size_t)mem_addr))
{
printf("mem_addr NOT exist...\n");
return -1;
}
debug_print_flag();
return 0;
}
int main(void)
{
void *pStart = NULL;
void *pAlloc = NULL;
size_t addr = 0x12345678;
pStart = InitMemPool(MEM_BLK_SIZE * 6);
assert(NULL != pStart);
printf("pStart = %p\n\n", pStart);
MemAlloc(MEM_BLK_SIZE * 2);
MemAlloc(MEM_BLK_SIZE * 1);
MemAlloc(MEM_BLK_SIZE * 2);
printf("input the address to free: ");
scanf("%x", &addr);
MemFree((void *)addr);
printf("input the address to free: ");
scanf("%x", &addr);
MemFree((void *)addr);
MemAlloc(MEM_BLK_SIZE * 3);
return 0;
} |
|