更多linux内核視頻教程文檔資料免費領取後台私信【内核】自行獲取.
二、原理
void* MemoryBlock::operator new(size_t, int nUnitSize,int nUnitAmount )
{
return ::operator new( sizeof(MemoryBlock) nUnitSize * nUnitAmount );
}
MemoryBlock::MemoryBlock( int nUnitSize,int nUnitAmount )
: nSize (nUnitAmount * nUnitSize),
nFree (nUnitAmount - 1), //構造的時候,就已将第一個單元分配出去了,所以減一
nFirst (1), //同上
pNext (NULL)
{
//初始化數組鍊表,将每個分配單元的下一個分配單元的序号寫在當前單元的前兩個字節中
char* pData = aData;
//最後一個位置不用寫入
for( int i = 1; i < nSize - 1; i )
{
(*(USHORT*)pData) = i;
pData = nUnitSize;
}
}
void CTest::operator delete( void* pTest )
{
Pool.Free(pTest);
}
void* CTest::operator new(size_t)
{
return (CTest*)Pool.Alloc();
}
#include <stdlib.h>
#include <wtypes.h>
#define MEMPOOL_ALIGNMENT 8 //對齊長度
//内存塊,每個内存塊管理一大塊内存,包括許多分配單元
class MemoryBlock
{
public:
MemoryBlock (int nUnitSize,int nUnitAmount);
~MemoryBlock(){};
static void* operator new (size_t,int nUnitSize,int nUnitAmount);
static void operator delete (void* ,int nUnitSize,int nUnitAmount){};
static void operator delete (void* pBlock);
int nSize; //該内存塊的大小,以字節為單位
int nFree; //該内存塊還有多少可分配的單元
int nFirst; //當前可用單元的序号,從0開始
MemoryBlock* pNext; //指向下一個内存塊
char aData[1]; //用于标記分配單元開始的位置,分配單元從aData的位置開始
};
class MemoryPool
{
public:
MemoryPool (int _nUnitSize,
int _nGrowSize = 1024,
int _nInitSzie = 256);
~MemoryPool();
void* Alloc();
void Free(void* pFree);
private:
int nInitSize; //初始大小
int nGrowSize; //增長大小
int nUnitSize; //分配單元大小
MemoryBlock* pBlock; //内存塊鍊表
};
#include "MemoryPool.h"
MemoryBlock::MemoryBlock( int nUnitSize,int nUnitAmount )
: nSize (nUnitAmount * nUnitSize),
nFree (nUnitAmount - 1), //構造的時候,就已将第一個單元分配出去了,所以減一
nFirst (1), //同上
pNext (NULL)
{
//初始化數組鍊表,将每個分配單元的下一個分配單元的序号寫在當前單元的前兩個字節中
char* pData = aData;
//最後一個位置不用寫入
for( int i = 1; i < nSize - 1; i )
{
(*(USHORT*)pData) = i;
pData = nUnitSize;
}
}
void* MemoryBlock::operator new(size_t, int nUnitSize,int nUnitAmount )
{
return ::operator new( sizeof(MemoryBlock) nUnitSize * nUnitAmount );
}
void MemoryBlock::operator delete( void* pBlock)
{
::operator delete(pBlock);
}
MemoryPool::MemoryPool( int _nUnitSize, int _nGrowSize /*= 1024*/, int _nInitSzie /*= 256*/ )
{
nInitSize = _nInitSzie;
nGrowSize = _nGrowSize;
pBlock = NULL;
if(_nUnitSize > 4)
nUnitSize = (_nUnitSize (MEMPOOL_ALIGNMENT - 1)) & ~(MEMPOOL_ALIGNMENT - 1);
else if( _nUnitSize < 2)
nUnitSize = 2;
else
nUnitSize = 4;
}
MemoryPool::~MemoryPool()
{
MemoryBlock* pMyBlock = pBlock;
while( pMyBlock != NULL)
{
pMyBlock = pMyBlock->pNext;
delete(pMyBlock);
}
}
void* MemoryPool::Alloc()
{
if( NULL == pBlock)
{
//首次生成MemoryBlock,new帶參數,new了一個MemoryBlock類
pBlock = (MemoryBlock*)new(nUnitSize,nInitSize) MemoryBlock(nUnitSize,nUnitSize);
return (void*)pBlock->aData;
}
//找到符合條件的内存塊
MemoryBlock* pMyBlock = pBlock;
while( pMyBlock != NULL && 0 == pMyBlock->nFree )
pMyBlock = pMyBlock->pNext;
if( pMyBlock != NULL)
{
//找到了,進行分配
char* pFree = pMyBlock->aData pMyBlock->nFirst * nUnitSize;
pMyBlock->nFirst = *((USHORT*)pFree);
pMyBlock->nFree--;
return (void*)pFree;
}
else
{
//沒有找到,說明原來的内存塊都滿了,要再次分配
if( 0 == nGrowSize)
return NULL;
pMyBlock = (MemoryBlock*)new(nUnitSize,nGrowSize) MemoryBlock(nUnitSize,nGrowSize);
if( NULL == pMyBlock)
return NULL;
//進行一次插入操作
pMyBlock->pNext = pBlock;
pBlock = pMyBlock;
return (void*)pMyBlock->aData;
}
}
void MemoryPool::Free( void* pFree )
{
//找到p所在的内存塊
MemoryBlock* pMyBlock = pBlock;
MemoryBlock* PreBlock = NULL;
while ( pMyBlock != NULL && ( pBlock->aData > pFree || pMyBlock->aData pMyBlock->nSize))
{
PreBlock = pMyBlock;
pMyBlock = pMyBlock->pNext;
}
if( NULL != pMyBlock ) //該内存在本内存池中pMyBlock所指向的内存塊中
{
//Step1 修改數組鍊表
*((USHORT*)pFree) = pMyBlock->nFirst;
pMyBlock->nFirst = (USHORT)((ULONG)pFree - (ULONG)pMyBlock->aData) / nUnitSize;
pMyBlock->nFree ;
//Step2 判斷是否需要向OS釋放内存
if( pMyBlock->nSize == pMyBlock->nFree * nUnitSize )
{
//在鍊表中删除該block
delete(pMyBlock);
}
else
{
//将該block插入到隊首
PreBlock = pMyBlock->pNext;
pMyBlock->pNext = pBlock;
pBlock = pMyBlock;
}
}
}
#include <stdio.h>
#include "MemoryPool.h"
class CTest
{
public:
CTest(){data1 = data2 = 0;};
~CTest(){};
void* operator new (size_t);
void operator delete(void* pTest);
public:
static MemoryPool Pool;
int data1;
int data2;
};
void CTest::operator delete( void* pTest )
{
Pool.Free(pTest);
}
void* CTest::operator new(size_t)
{
return (CTest*)Pool.Alloc();
}
MemoryPool CTest::Pool(sizeof(CTest));
int main()
{
CTest* pTest = new CTest;
printf("%d",pTest->data2);
}
static void* operator new (size_t,int nUnitSize,int nUnitAmount);
static void operator delete (void* ,int nUnitSize,int nUnitAmount){};
4. 帶參數的new操作符
pBlock = (MemoryBlock*)new(nUnitSize,nInitSize) MemoryBlock(nUnitSize,nUnitSize);
5. 如果在類的内部不能進行靜态成員的定義的話,可以隻在内部進行聲明,在外部定義:
MemoryPool CTest::Pool(sizeof(CTest));
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!