📄 virtual.c
字号:
idxSrcStartBlk = BLOCK_INDEX( dwSrcAddress );
lpSegSrc = Seg_FindSegment( dwSrcAddress );
if( lpSegSrc == NULL )
goto _RET_INVALID_LEAVE;
idxFirstBlk = Seg_SearchFirstBlock( lpSegSrc, idxSrcStartBlk );
if( idxFirstBlk == NOT_FIND_FIRST )
goto _RET_INVALID_LEAVE;
// 保证所用需要的page已被提交。
uiAllocPages = Seg_ReviewRegion( lpSegSrc, idxFirstBlk, idxSrcStartBlk, idxSrcStartPage, uiNeedPages, &uiCountPages );
if( uiAllocPages || uiCountPages != uiNeedPages )
goto _RET_INVALID_LEAVE;
bRetv = Seg_Copy( lpProcessSegDst, lpSegDst, idxDstStartBlk, idxDstStartPage, uiNeedPages, lpSegSrc, idxSrcStartBlk, dwProtect );
}
else
{ // 源是物理地址,直接映射。phy address
bRetv = Seg_MapPhyPages( lpProcessSegDst, lpSegDst, idxDstStartBlk, idxDstStartPage, uiNeedPages, uiNeedAllocPages, MEM_PHYSICAL | MEM_CONTIGUOUS, (DWORD*)dwPhyAdr, dwProtect );
}
}
if( bRetv )
FlushCacheAndClearTLB(); // 因为有重新映射,必须刷新CACHE
KL_LeaveCriticalSection( &csVirtualMem );//离开冲突段
return bRetv;
_RET_INVALID_LEAVE:
KL_LeaveCriticalSection( &csVirtualMem );
_RET_INVALID:
KL_SetLastError( ERROR_INVALID_PARAMETER );
WARNMSG( DEBUG_VIRTUALCOPY, ( "DoVirtaulCopy:failure alloc.\r\n" ) );
return bRetv;
}
// ********************************************************************
// 声明:BOOL WINAPI KL_VirtualCopy(
// LPVOID lpvDest,
// LPVOID lpvSrc,
// DWORD cbSize,
// DWORD fdwProtect )
// 参数:
// IN dwDstAddress - 目标地址
// IN dwSrcAddress - 源地址
// IN dwSize - 需要拷贝的大小
// IN dwProtect - 保护属性
// 返回值:
// 假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 将源地址的物理页映射到目标地址
// 引用:
// 系统API
// ********************************************************************
#define DEBUG_KL_VirtualCopy 0
BOOL WINAPI KL_VirtualCopy(
LPVOID lpvDest,
LPVOID lpvSrc,
DWORD cbSize,
DWORD fdwProtect )
{
DEBUGMSG( DEBUG_KL_VirtualCopy, ( "KL_VirtualAlloc entry,lpvDest=0x%x,lpvSrc=0x%x,cbSize=%d.\r\n", lpvDest, lpvSrc, cbSize ) );
return DoVirtualCopy( (DWORD)lpvDest, (DWORD)lpvSrc, cbSize, fdwProtect ) ? TRUE : FALSE;
}
// ********************************************************************
// 声明:static BOOL DoVirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
// 参数:
// IN lpAddress - 虚地址
// IN dwSize - 虚内存大小
// IN dwFreeType - 释放类型,可以为:
// MEM_DECOMMIT - 释放一段区域的物理页
// MEM_RELEASE - 释放整个域,dwSize必须为0
// 返回值:
// 假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 释放虚内存域/地址
// 引用:
//
// ********************************************************************
static BOOL DoVirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
{
DWORD dwStart = (DWORD)lpAddress;
DWORD dwSegIndex;
int idxFirstBlk, idxStartBlk, idxPage;
int iPages;
LPSEGMENT lpSeg;
LPPROCESS_SEGMENTS lpProcessSeg;
BOOL bRetv = FALSE;
BOOL bFlush = FALSE;
// check param
// 检查参数是否有效
if( lpAddress == NULL ||
( (dwFreeType & MEM_RELEASE) && dwSize ) )
{
KL_SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
KL_EnterCriticalSection( &csVirtualMem );
dwSegIndex = GET_SEGMENT_INDEX( dwStart );
if( ( lpProcessSeg = Seg_FindProcessSegment( dwStart ) ) &&
( lpSeg = lpProcessSeg->lpSeg ) ) // 得到地址对应的段指针
{
idxStartBlk = BLOCK_INDEX( dwStart );
idxFirstBlk = Seg_SearchFirstBlock( lpSeg, idxStartBlk ); // 得到该域的第一个块
idxPage = PAGE_INDEX( dwStart );
if( idxFirstBlk != NOT_FIND_FIRST ) // 块有效吗 ?
{ // 有效
int iReserved;
int iCountPages = 0;
if( dwFreeType == MEM_DECOMMIT && dwSize )
{ // 释放一段区域
iPages = ( ( dwStart + dwSize + PAGE_SIZE - 1 ) >> PAGE_SHIFT ) - ( dwStart >> PAGE_SHIFT );
// 统计保留的页数 和 已分配的页数
iReserved = Seg_ReviewRegion( lpSeg, idxFirstBlk, idxStartBlk, idxPage, iPages, &iCountPages );
if( iCountPages >= iPages )
{
if( iReserved != iPages )
{ //先刷新CACHE
FlushCacheAndClearTLB();
bFlush |= Seg_DecommitPages( lpProcessSeg, lpSeg, idxStartBlk, idxPage, iPages );
bRetv = TRUE;
goto _return;
}
}
else
{ //error
ASSERT( 0 );
}
}
else if( dwFreeType & MEM_RELEASE )
{ //释放整个域
if( idxPage == 0 && idxFirstBlk == idxStartBlk )
{ // 统计保留的页数 和 已分配的页数
iReserved = Seg_ReviewRegion( lpSeg, idxFirstBlk, idxStartBlk, 0, -1, &iCountPages );
if( iReserved != iCountPages )
{
FlushCacheAndClearTLB();
bFlush |= Seg_DecommitPages( lpProcessSeg, lpSeg, idxStartBlk, 0, iCountPages );
}
// 释放该域已定位的块
Seg_FreeRegion( lpSeg, idxStartBlk );
bRetv = TRUE;
goto _return;
}
}
}
}
_return:
//调用Seg_DecommitPages之前已经调用了FlushCacheAndClearTLB,这里必要吗 ?
if( bFlush )
FlushCacheAndClearTLB();
KL_LeaveCriticalSection( &csVirtualMem );
return bRetv;
}
// ********************************************************************
// 声明:BOOL WINAPI KL_VirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
// IN lpAddress - 虚地址
// IN dwSize - 虚内存大小
// IN dwFreeType - 释放类型,可以为:
// MEM_DECOMMIT - 释放一段区域的物理页
// MEM_RELEASE - 释放整个域,dwSize必须为0
// 返回值:
// 假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 释放虚内存域/地址
// 引用:
// 系统API
// ********************************************************************
#define DEBUG_KL_VirtualFree 0
BOOL WINAPI KL_VirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
{
DEBUGMSG( DEBUG_KL_VirtualFree, ( "KL_VirtualFree entry,lpAddress=0x%x,dwSize=0x%x.\r\n", lpAddress, dwSize ) );
if( (DWORD)lpAddress < 0x80000000 )
return DoVirtualFree( lpAddress, dwSize, dwFreeType );
else
return FALSE;
}
// ********************************************************************
// 声明:BOOL WINAPI KC_VirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
// IN lpAddress - 虚地址
// IN dwSize - 虚内存大小
// IN dwFreeType - 释放类型,可以为:
// MEM_DECOMMIT - 释放一段区域的物理页
// MEM_RELEASE - 释放整个域,dwSize必须为0
// 返回值:
// 假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 释放虚内存域/地址
// 引用:
// 内核版
// ********************************************************************
#define DEBUG_KC_VirtualFree 0
BOOL WINAPI KC_VirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
{
DEBUGMSG( DEBUG_KC_VirtualFree, ( "KC_VirtualFree entry,lpAddress=0x%x,dwSize=0x%x.\r\n", lpAddress, dwSize ) );
return DoVirtualFree( lpAddress, dwSize, dwFreeType );
}
// ********************************************************************
// 声明:BOOL WINAPI KL_VirtualProtect( LPVOID lpvAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
// 参数:
// IN lpAddress - 虚地址
// IN dwSize - 虚内存大小
// IN flNewProtect - 新的保护属性
// IN lpfOldProtect - 之前的保护属性
// 返回值:
// 假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 重新设置内存域的页属性
// 引用:
// 系统API
// ********************************************************************
#define DEBUG_KL_VirtualProtect 0
BOOL WINAPI KL_VirtualProtect( LPVOID lpvAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
{
DWORD dwStart;// = (DWORD)lpvAddress;
DWORD dwSegIndex;// = GET_SEGMENT_INDEX( (DWORD)dwStart );
LPSEGMENT lpSeg;
DWORD dwError = 0;
LPPROCESS_SEGMENTS lpProcessSeg;
DEBUGMSG( DEBUG_KL_VirtualProtect, ( "KL_VirtualProtect entry,lpvAddress=0x%x,dwSize=0x%x.\r\n", lpvAddress, dwSize ) );
// 检查参数
if( dwSize == 0 ||
lpflOldProtect == NULL ||
lpvAddress == NULL )
{
KL_SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
dwStart = (DWORD)lpvAddress;
dwSegIndex = GET_SEGMENT_INDEX( (DWORD)dwStart );
KL_EnterCriticalSection( &csVirtualMem );
if( dwSegIndex < MAX_SEGMENTS )
{
if( ( lpProcessSeg = Seg_FindProcessSegment( dwStart ) ) &&
( lpSeg = lpProcessSeg->lpSeg ) ) // 得到虚地址对应的段指针
//if( ( lpSeg = Seg_FindSegment( dwStart ) ) ) // 得到虚地址所在的段
{
DWORD idxFirstBlk, idxStartBlk = BLOCK_INDEX( dwStart );
DWORD idxStartPage;
DWORD dwPages;
// 2004-01-28, this is a error, i will test it
//idxStartBlk = Seg_SearchFirstBlock( lpSeg, idxFirstBlk );
idxFirstBlk = Seg_SearchFirstBlock( lpSeg, idxStartBlk ); // 得到该内存域的第一个块
//if( idxStartBlk != NOT_FIND_FIRST )
if( idxFirstBlk != NOT_FIND_FIRST )
// 2004-01-28
{
idxStartPage = PAGE_INDEX( dwStart );
dwPages = ( ( dwStart + dwSize + PAGE_SIZE - 1 ) / PAGE_SIZE ) - ( dwStart / PAGE_SIZE );
// 扫描需要的页是否都已经提交
if( Seg_ScanCommitRegion( lpSeg, idxFirstBlk, idxStartBlk, idxStartPage, dwPages ) )
{ //是
DWORD dwNewAttrib;
//得到当前的属性
*lpflOldProtect = GetProtectFromAttrib( lpSeg->lpBlks[idxStartBlk]->uiPages[idxStartPage] );
dwNewAttrib = GetAttribFromProtect( flNewProtect );
if( dwNewAttrib )
{ //设置新的属性
Seg_ResetPageAttrib( lpProcessSeg, lpSeg, idxFirstBlk, idxStartBlk, idxStartPage, dwPages, dwNewAttrib );
FlushCacheAndClearTLB(); //刷新CACHE
}
}
}
else
{ // 虚地址无效
//ASSERT( 0 );
dwError = ERROR_INVALID_PARAMETER;
WARNMSG( DEBUG_KL_VirtualProtect, ( "KL_VirtualProtect: invalid address=0x%x,dwSize=0x%x.\r\n", lpvAddress, dwSize ) );
goto _err_return;
}
}
}
_err_return:
if( dwError )
KL_SetLastError( dwError );
KL_LeaveCriticalSection( &csVirtualMem );
return dwError ? FALSE : TRUE;
}
// ********************************************************************
// 声明:LPVOID WINAPI KL_AllocPhysMem(
// DWORD dwSize,
// DWORD fdwProtect,
// DWORD dwAlignmentMask,
// DWORD dwFlags,
// ULONG * pPhysicalAddress
// )
// 参数:
// IN dwSize - 需要分配的大小
// IN fdwProtect - 保护属性
// IN dwAlignmentMask - 开始地址对齐模式
// IN dwFlags - 标志
// OUT pPhysicalAddress - 用于接受分配的物理地址
// 返回值:
// 假如成功,返回非NULL的虚地址,pPhysicalAddress返回对应的物理地址;否则,返回NULL
// 功能描述:
// 分配连续的物理页
// 引用:
// 系统API
// ********************************************************************
#define DEBUG_KL_AllocPhysMem 0
LPVOID WINAPI KL_AllocPhysMem(
DWORD dwSize,
DWORD fdwProtect,
DWORD dwAlignmentMask,
DWORD dwFlags,
ULONG * pPhysicalAddress
)
{
void * p;
DWORD dwPageSize = ALIGN_PAGE_UP( dwSize );
LPVOID lpVAdr = NULL;
DEBUGMSG( DEBUG_KL_AllocPhysMem, ( "KL_AllocPhysMem entry,dwSize=0x%x.\r\n", dwSize ) );
KL_EnterCriticalSection( &csVirtualMem );
// 得到连续的页
p = Page_GetContiguous( dwPageSize / PAGE_SIZE, dwAlignmentMask );
if( p )
{ //
DWORD dwPhysicalAddress = _GetPhysicalPageAdr( (DWORD)p ); // 得到p对应的物理地址
//将p映射到用户空间
lpVAdr = DoVirtualAlloc( NULL,
dwPageSize,
MEM_COMMIT | MEM_RESERVE | MEM_PHYSICAL | MEM_CONTIGUOUS,
fdwProtect | PAGE_NOCACHE,
(LPVOID)dwPhysicalAddress );
if( lpVAdr )
{
*pPhysicalAddress = dwPhysicalAddress;
}
else
{ //失败。
Page_ReleaseContiguous( p, dwPageSize / PAGE_SIZE );
}
}
KL_LeaveCriticalSection( &csVirtualMem );
return lpVAdr;
}
// ********************************************************************
// 声明:BOOL WINAPI KL_FreePhysMem( LPVOID lpvAddress )
// 参数:
// IN lpvAddress - 虚地址(用KL_AllocPhysMem分配的虚地址)
// 返回值:
// 假如成功,返回TRUE; 否则,返回FALSE
// 功能描述:
// 释放之前用 KL_AllocPhysMem 分配的地址
// 引用:
// 系统API
// ********************************************************************
#define DEBUG_KL_FreePhysMem 0
BOOL WINAPI KL_FreePhysMem( LPVOID lpvAddress )
{
DEBUGMSG( DEBUG_KL_FreePhysMem, ( "KL_FreePhysMem entry,lpvAddress=0x%x.\r\n", lpvAddress ) );
return DoVirtualFree( lpvAddress, 0, MEM_RELEASE );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -