📄 klheap.c
字号:
/******************************************************
Copyright(c) 版权所有,1998-2003微逻辑。保留所有权利。
******************************************************/
/*****************************************************
文件说明:程序堆管理
版本号:2.0.0
开发时期:2000
作者:李林
修改记录:
2003-05-14: 将API调用改为 Kernerl调用, By ln
2003-05-13: 增加 互斥段代码, By ln
2003-05-12: HeapAlloc 增加 HEAP_ZERO_MEMORY , By ln
2003-05-09: LN, 将堆的必须限制改为可选择限制, By ln
******************************************************/
#include <eframe.h>
#include <epheap.h>
#include <coresrv.h>
#include <epalloc.h>
#define DISABLE()
#define ENABLE()
#define BUSY_FLAG 1 /* use this define for the BUSY_FLAG bit in lpNext */
#define ALLOC_FLAG 2
#define IS_BUSY(x) ((long)(x)->busy.lpNext&BUSY_FLAG)
#define IS_ALLOC(x) ((long)(x)->busy.lpNext&ALLOC_FLAG)
// 对齐8bytes
#define ALIGNMASK (7)//sizeof(char*)<=2? 1: (sizeof(char*)<=4? 3: 7))
//
static void _InsertToFree( LPHEAP, LPBLOCK );
static void _RemoveFromFree( LPHEAP, LPBLOCK );
static BOOL Heap_AddToSection( LPHEAP lpHeap, LPSECTION lp, ULONG ulLen );
// 互斥操作,进入
#define EnterCriticalLock( lpHeap, bSerial ) \
do{ \
if( (bSerial) && ( (lpHeap)->dwOption & HEAP_NO_SERIALIZE ) == 0 ) \
{ \
KL_EnterCriticalSection( &(lpHeap)->csHeap );\
} \
}while(0);
// 互斥操作,离开
#define LeaveCriticalLock( lpHeap, bSerial ) \
do{ \
if( (bSerial) && ( (lpHeap)->dwOption & HEAP_NO_SERIALIZE ) == 0 ) \
{ \
KL_LeaveCriticalSection( &(lpHeap)->csHeap );\
} \
}while(0);
#define PAGE_SIZE (4*1024)
#define ALLOC_SIZE (64*1024)
/**************************************************
声明:BOOL Heap_Init( LPHEAP lpHeap, DWORD dwOption, ULONG ulInitialSize, ULONG ulLimit )
参数:
lpHeap - HEAP 结构指针,用于保存堆信息
dwOption - 附加的功能,可以为以下值:
HEAP_NO_SERIALIZE - 以后的HeapAlloc, HeapFree等功能不需要串行化(互斥操作)
HEAP_VIRTUAL_ALLOC - 从系统内存空间分配内存的方法,该值说明用VirtualAlloc功能从系统分配;
否则,用DoAllocPageMem功能从系统分配
ulInitialSize - 初始化堆尺寸
ulLimit - 堆尺寸最大限制
返回值:
假如成功,TRUE;否则,返回FALSE
功能描述:
初始化一个堆,以便与于以后的堆操作
引用:
************************************************/
BOOL Heap_Init( LPHEAP lpHeap, DWORD dwOption, ULONG ulInitialSize, ULONG ulLimit )
{
if( ulInitialSize > ulLimit )
return FALSE;
memset( lpHeap, 0, sizeof( HEAP ) );
if( (dwOption & HEAP_NO_SERIALIZE) == 0 )
{
KL_InitializeCriticalSection( &lpHeap->csHeap );
}
lpHeap->dwOption = dwOption;
ulInitialSize = (ulInitialSize + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1));
ulLimit = (ulLimit + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1));
lpHeap->dwHeapSizeLimit = ulLimit;
#ifdef VIRTUAL_MEM
if( dwOption & HEAP_VIRTUAL_ALLOC )
{
BOOL bRetv = TRUE;
if( ulLimit || ulInitialSize )
{ // 预留内存
DWORD dwReverse = MAX( ulLimit, ulInitialSize );
LPVOID lpv;
lpv = KL_VirtualAlloc( 0, dwReverse, MEM_RESERVE, PAGE_READWRITE );
if( lpv )
{
lpHeap->lpbCur = lpHeap->lpbCurReserveBase = lpv;
lpHeap->dwCurReserveSize = dwReverse;
lpHeap->dwCurUseSize = 0;
lpHeap->dwTotalReserveSize = dwReverse;
}
else
bRetv = FALSE;
}
if( ulInitialSize && lpHeap->lpbCurReserveBase )
{ // 提交物理内存
DWORD dwCommitSize;
LPVOID p;
ulInitialSize = MAX( ulInitialSize, sizeof( SECTION ) );
dwCommitSize = (ulInitialSize + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1));
p = KL_VirtualAlloc( lpHeap->lpbCur, dwCommitSize, MEM_COMMIT, PAGE_READWRITE );
if( p == NULL )
{
bRetv = FALSE;
KL_VirtualFree( lpHeap->lpbCurReserveBase, 0, MEM_RELEASE );
lpHeap->lpbCurReserveBase = lpHeap->lpbCur = NULL;
lpHeap->dwCurReserveSize = 0;
lpHeap->dwTotalReserveSize = 0;
}
else
{
lpHeap->dwTotalCommitSize = dwCommitSize;
lpHeap->lpbCur += sizeof( SECTION );
lpHeap->dwCurUseSize += sizeof( SECTION );
Heap_AddToSection( lpHeap, p, lpHeap->dwTotalReserveSize );
}
}
//RETAILMSG( 1, ( "Heap_Init:lpHeap=%x.\r\n", lpHeap ) );
return bRetv;
}
//#else
else
#endif //VIRTUAL_MEM
return TRUE;
//#endif
}
/**************************************************
声明:HANDLE DoHeapCreate( DWORD flOptions, ULONG dwInitialSize, ULONG dwMaximumSize )
参数:
flOptions - 附加的功能,可以为以下值:
HEAP_NO_SERIALIZE - 以后的HeapAlloc, HeapFree等功能不需要串行化(互斥操作)
HEAP_VIRTUAL_ALLOC - 从系统内存空间分配内存的方法,该值说明用VirtualAlloc功能从系统分配;
否则,用DoAllocPageMem功能从系统分配
dwInitialSize - 初始化堆尺寸
dwMaximumSize - 堆尺寸最大限制
返回值:
假如成功,有效的句柄;否则,返回NULL
功能描述:
初始化一个堆,以便与于以后的堆操作
引用:
process.c用该函数去初始化进程堆
************************************************/
HANDLE DoHeapCreate( DWORD flOptions, ULONG dwInitialSize, ULONG dwMaximumSize )
{
LPHEAP lpHeap = KHeap_Alloc( sizeof( HEAP ) );
if( lpHeap )
{
if( Heap_Init( lpHeap, flOptions, dwInitialSize, dwMaximumSize ) == FALSE )
{
KHeap_Free( lpHeap, sizeof( HEAP ) );
lpHeap = NULL;
}
}
return lpHeap;
}
/**************************************************
声明:BOOL WINAPI DoHeapDestroy( HANDLE hHeap )
参数:
hHeap - 堆句柄(为之前调用KL_HeapCreate所返回的句柄)
返回值:
假如成功,返回TRUE; 否则,返回FALSE
功能描述:
破坏堆的部分数据
引用:
内核调用
************************************************/
BOOL DoHeapDestroy( LPHEAP lpHeap )
{
// LPHEAP lpHeap = (LPHEAP)hHeap;
// 1.因为 用户堆的链表指针也是在用户堆里,其指针也有可能被破坏,
// 如果是这样,在调用KL_HeapDestroy有可能出现异常,所以这里不用去释放 heap
// 2.Seg 管理器会释放所有的用户空间(包括用户堆)
// 3.内核在释放进程时会调用该函数
// 进入互斥段
if( lpHeap )
{
if( (lpHeap->dwOption & HEAP_NO_SERIALIZE) == 0 )
KL_DeleteCriticalSection( &lpHeap->csHeap );
// 释放分配的堆信息结构
KHeap_Free( lpHeap, sizeof( HEAP ) );
return TRUE;
}
return FALSE;
}
/**************************************************
声明:HANDLE WINAPI KL_HeapCreate( DWORD flOptions, ULONG dwInitialSize, ULONG dwMaximumSize )
参数:
flOptions - 附加的功能,可以为以下值:
HEAP_NO_SERIALIZE - 以后的HeapAlloc, HeapFree等功能不需要串行化(互斥操作)
dwInitialSize - 初始化堆尺寸
dwMaximumSize - 堆尺寸最大限制
返回值:
假如成功,有效的句柄;否则,返回NULL
功能描述:
初始化一个堆,以便与于以后的堆操作
引用:
系统API调用
************************************************/
HANDLE WINAPI KL_HeapCreate( DWORD flOptions, ULONG dwInitialSize, ULONG dwMaximumSize )
{
//
#ifdef VIRTUAL_MEM
return DoHeapCreate( flOptions|HEAP_VIRTUAL_ALLOC, dwInitialSize, dwMaximumSize );
#else
flOptions &= ~HEAP_VIRTUAL_ALLOC;
return DoHeapCreate( flOptions, dwInitialSize, dwMaximumSize );
#endif
}
/**************************************************
声明:static BOOL Heap_AddToSection( LPHEAP lpHeap, LPSECTION lp, ULONG ulLen )
参数:
lpHeap - HEAP 结构指针,指向堆信息
lpsc - SECTION 结构指针,向堆增加的新内存段
ulLen - 新内存段尺寸
返回值:
假如成功,返回TRUE;否则,返回FALSE
功能描述:
将一个新内存段加入堆链表
引用:
************************************************/
static BOOL Heap_AddToSection( LPHEAP lpHeap, LPSECTION lpsc, ULONG ulLen )
{
// 初始化SECTION 结构
lpsc->ulLen = ulLen;
lpsc->lpNext = lpHeap->lpSection;
// 加入堆链表
lpHeap->lpSection = lpsc;
return TRUE;
}
/**************************************************
声明:void * GetSystemMem( LPHEAP lpHeap, DWORD dwSize, DWORD * lpdwRealSize )
参数:
lpHeap - HEAP 结构指针,指向堆信息
dwSize - 需要的内存大小
lpdwRealSize - 返回的真实内存大小( > dwSize )
返回值:
假如成功,返回非NULL的内存指针;否则,返回NULL
功能描述:
既然堆里没有足够的内存块,则用该函数从系统内存分配内存块,并将其加入堆链表
引用:
Heap_Alloc, Heap_Realloc
************************************************/
#define DEBUG_GETSYSTEMMEM 0
static void * GetSystemMem( LPHEAP lpHeap, DWORD dwSize, DWORD * lpdwRealSize )
{
//RETAILMSG( 1, ( "GetSystemMem:lpHeap=%x,dwSize=%d,ProcessId=%d.\r\n", lpHeap, dwSize, KL_GetCurrentProcessId() ) );
#ifdef VIRTUAL_MEM
// 如果系统有MMU管理,则用该段代码
if( lpHeap->dwOption & HEAP_VIRTUAL_ALLOC )
{ // 用VirtualAlloc去分配内存
void * p = NULL;
DWORD dwCommitSize;
UINT uiNewSectionSize = 0;
*lpdwRealSize = 0;
dwCommitSize = (dwSize + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1)); // align to page
if( lpHeap->dwCurUseSize + dwCommitSize > lpHeap->dwCurReserveSize )
{ // 当前堆里未提交(保留)的内存域 小于 需要的内存尺寸,必须分配新的内存域/段
//dwSize += sizeof(SECTION);
if( lpHeap->dwHeapSizeLimit )
{ // 如果有整个堆的大小限制,则错误。
RETAILMSG( 1, ( "error: GetSystemMem:Heap reach size limite(%d).\r\n", lpHeap->dwHeapSizeLimit ) );
return NULL;
}
else
{ // 没有尺寸限制,分配一个新的
DWORD dwReserveSize = dwSize + sizeof(SECTION);
// 对齐到ALLOC_SIZE大小
dwReserveSize = (dwReserveSize + ALLOC_SIZE - 1) & (~(ALLOC_SIZE - 1));// align to 64k
// 先保留内存域
lpHeap->lpbCurReserveBase = KL_VirtualAlloc( 0, dwReserveSize, MEM_RESERVE, PAGE_READWRITE );
if( lpHeap->lpbCurReserveBase == NULL )
{ //保留内存域失败
WARNMSG( DEBUG_GETSYSTEMMEM, ( "error: GetSystemMem: can't to reserve space size(%d).\r\n", dwReserveSize ) );
dwReserveSize = 0;
}
else
uiNewSectionSize = sizeof(SECTION);
// 初始化新的内存域
lpHeap->lpbCur = lpHeap->lpbCurReserveBase;
lpHeap->dwCurReserveSize = dwReserveSize;
lpHeap->dwCurUseSize = 0;
lpHeap->dwTotalReserveSize += dwReserveSize;
}
}
if( lpHeap->dwHeapSizeLimit &&
lpHeap->dwCurUseSize == NULL )
uiNewSectionSize = sizeof(SECTION); // 为section保留空间
// 真实的需要提交/分配的内存
dwCommitSize = (dwSize + uiNewSectionSize + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1));
// 合法检查
if( lpHeap->dwCurUseSize + dwCommitSize <= lpHeap->dwCurReserveSize )
{ // 提交/分配新的内存块
p = KL_VirtualAlloc( lpHeap->lpbCur, dwCommitSize, MEM_COMMIT, PAGE_READWRITE );
if( p )
{
#ifdef __DEBUG
memset( p, 0xCCCCCCCC, dwCommitSize );
#endif
if( uiNewSectionSize )
{ // 需要将其加入堆链表
Heap_AddToSection( lpHeap, (LPSECTION)p, lpHeap->dwCurReserveSize );
p = (LPBLOCK)( (DWORD)p + uiNewSectionSize );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -