📄 virtual.c
字号:
{ // 有有效的物理页,释放它
DEBUGMSG( DEBUG_SEG_DECOMMITPAGES, ( "Phy=%x,b=%d,p=%d.\r\n", *lpui, idxStartBlk, idxStartPages ) );
Page_Free( (LPVOID)_GetVirtualPageAdr( *lpui ) );
*lpui = 0;
//更新页表-2005-02-03
if( bWriteToSecondPage &&
PAGE_IN_RANGE( uStartPage, uMinPage, uMaxPage ) )
{
lpProcessSeg->lpdwSecondPageTable[uStartPage] = *lpui;
}
bFlush = TRUE; //刷新CACHE
}
uStartPage++;
iPages--;
lpui++;
idxStartPages++;
}
}
idxStartPages = 0;
lppBlks++;//下一个块
}
return bFlush;
}
// ********************************************************************
// 声明:BOOL AutoCommitPage( LPMEMBLOCK lpBlk, int idxStartPage )
// 参数:
// IN lpBlk - MEMBLOCK(内存块)结构指针
// IN idxStartPage - 块内的开始页
// 返回值:
// 假如提交成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 自动提交物理页。通常被异常处理调用
// 引用:
//
// ********************************************************************
// handle by exception handler
#define DEBUG_AUTOCOMMITPAGE 0
//BOOL AutoCommitPage( LPMEMBLOCK lpBlk, int idxStartPage )
BOOL AutoCommitPage( LPMEMBLOCK lpBlk, DWORD dwAddress )
{
UINT uiPhyPage;
DWORD dwPhyFlagMask = GetPhyPageFlagMask();
int idxStartPage = PAGE_INDEX( dwAddress );
LPPROCESS_SEGMENTS lpProcessSeg;
ASSERT( lpBlk->uiPages[idxStartPage] == 0 );
uiPhyPage = (UINT)Page_Alloc( TRUE );//cache 地址
if( uiPhyPage )
{
#ifdef __DEBUG
// 这里是否有一个错误 ?!,因为uiPhyPage是内核CACHE地址>0x80000000,
// 而该页随后要被用到,并且是已另一个CACHE地址 < 0x80000000 出现.
// 因此我用UNCACHE地址去清除
//memset( (LPVOID)uiPhyPage, 0xCCCCCCCC, PAGE_SIZE );
//
memset( (LPVOID)CACHE_TO_UNCACHE(uiPhyPage), 0xCCCCCCCC, PAGE_SIZE );
//
#endif
// 得到对应的物理页和属性组合
uiPhyPage = _GetPhysicalPageAdr( uiPhyPage ) | (lpBlk->uiFlag & dwPhyFlagMask);
lpBlk->uiPages[idxStartPage] = uiPhyPage;
if( ( lpProcessSeg = Seg_FindProcessSegment( dwAddress ) ) )
{
ASSERT( lpProcessSeg->lpdwSecondPageTable );
if( PAGE_INDEX_IN_SEGMENT( dwAddress ) >= lpProcessSeg->uiPageTableStart &&
PAGE_INDEX_IN_SEGMENT( dwAddress ) < lpProcessSeg->uiPageTableStart + PAGES_PER_MEGA )
{
lpProcessSeg->lpdwSecondPageTable[PAGE_INDEX_IN_MEGA( dwAddress )] = uiPhyPage;
}
}
DEBUGMSG( DEBUG_AUTOCOMMITPAGE, ( "auto commit sucess=%x.\r\n", uiPhyPage ) );
}
else
{
#ifdef __DEBUG
RETAILMSG( 1, ( "auto commit error: no physical page!!! .\r\n" ) );
RETAILMSG( 1, ( "auto commit error: no physical page!!! .\r\n" ) );
RETAILMSG( 1, ( "auto commit error: no physical page!!! .\r\n" ) );
RETAILMSG( 1, ( "auto commit error: no physical page!!! .\r\n" ) );
while(1);//ASSERT( 0 ); // no physical page!!!
#else
return FALSE;
#endif
}
return TRUE;
}
// ********************************************************************
// 声明:BOOL Seg_MapPhyPages(
// LPPROCESS_SEGMENTS lpProcessSeg,
// LPSEGMENT lpSeg,
// int idxCommitBlk,
// int idxPageOffset,
// int iNeedPages,
// int iAllocPages,
// UINT uiAllocType,
// DWORD * lpdwPhycialPages,
// DWORD dwProtect
// )
// 参数:
// IN lpProcessSeg - 进程段组
// IN lpSeg - 段结构指针
// IN idxCommitBlk - 需要提交的开始块
// IN idxPageOffset - 开始块内的开始页
// IN iNeedPages - 需要查找的页
// IN iAllocPages - 需要提交的页
// IN uiAllocType - 分配类型,为以下值:
// MEM_PHYSICAL - lpdwPhycialPages 包含物理页,如果没有MEM_CONTIGUOUS属性,
// 则 lpdwPhycialPages[n] 包含第n个物理页。
// 如果没有该属性,则由该函数分配物理页
// MEM_CONTIGUOUS - 物理页是连续的,并且lpdwPhycialPages本身表示物理页地址的开始
// IN lpdwPhycialPages - 指向物理页或物理页地址(依赖于uiAllocType)。
// IN dwProtect - 保护属性
// 返回值:
// 假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 将物理页映射到相应的虚空间
// 引用:
//
// ********************************************************************
#define DEBUG_SEG_MAPPHYPAGES 0
BOOL Seg_MapPhyPages(
LPPROCESS_SEGMENTS lpProcessSeg,
LPSEGMENT lpSeg,
int idxCommitBlk,
int idxPageOffset,
int iNeedPages,
int iAllocPages,
UINT uiAllocType,
DWORD * lpdwPhycialPages,
DWORD dwProtect
)
{
LPMEMBLOCK * lppBlks = lpSeg->lpBlks + idxCommitBlk; // 开始页
LPMEMBLOCK lpBlk;
int iPages = 0;
BOOL bFlush = FALSE;
UINT uStartPage, uMinPage, uMaxPage;
BOOL bWriteToSecondPage;
if( (uiAllocType & MEM_PHYSICAL) == 0 ) //由本函数分配物理页吗 ?
{ // 是
if( Page_Lock( iAllocPages ) == FALSE ) // 锁住需要的页
{ // 不成功
WARNMSG( DEBUG_SEG_MAPPHYPAGES, ( "Seg_MapPhyPages: failure to LockPages=%d.\r\n", iAllocPages ) );
return FALSE;
}
}
// 得到CPU对应的页属性
dwProtect = GetAttribFromProtect( dwProtect );
//需要CACHE ?-2005-02-02
uMinPage = uStartPage = idxCommitBlk * PAGES_PER_BLOCK + idxPageOffset;
uMaxPage = uStartPage + iNeedPages;
bWriteToSecondPage = GetPagesInCacheRange( lpProcessSeg, &uMinPage, &uMaxPage );
//
while( iPages < iNeedPages )
{
lpBlk = *lppBlks++;
ASSERT( lpBlk && lpBlk > RESERVED_BLOCK );
// 搜索块内的所有页,search the block's all pages
while( idxPageOffset < PAGES_PER_BLOCK &&
iPages < iNeedPages )
{
if( lpBlk->uiPages[idxPageOffset] == 0 ) // 分配了物理页吗 ?
{ // 没有,为其分配一个。now, to alloc a physical page
int iTryCount = 0;
UINT uiPhyPage;
// 虽然不应该出现没有物理页的情况,之前已用Page_Lock锁住需要的页面,但多试几次也无访
// 不过,现在我觉得应该将循环检查的代码 移到 Page_Lock 部分!!!!
// 改变它以后
for( ; iTryCount < 10; iTryCount++ )
{
if( (uiAllocType & MEM_PHYSICAL) == 0 )
{ // 自动分配
uiPhyPage = (UINT)Page_Alloc( FALSE );
if( uiPhyPage )
uiPhyPage = _GetPhysicalPageAdr( uiPhyPage );
}
else
{ //用参数给的物理地址 MEM_PHYSICAL
if( uiAllocType & MEM_CONTIGUOUS )
{ // 连续的地址,lpdwPhycialPages本身就是物理页地址
uiPhyPage = (UINT)lpdwPhycialPages; // 当前的物理页地址
lpdwPhycialPages = (DWORD*)NEXT_PHYSICAL_PAGE( lpdwPhycialPages );
}
else
{ // 非连续的物理页,physical pages is not contigous, put in the pointer
uiPhyPage = *lpdwPhycialPages;
lpdwPhycialPages++; // 下一个物理页
}
}
if( uiPhyPage )
{
uiPhyPage |= dwProtect; // 或上保护属性
lpBlk->uiPages[idxPageOffset] = uiPhyPage;
bFlush = TRUE; // 刷新CACHE
//2005-02-02是否CACHE
if( bWriteToSecondPage &&
PAGE_IN_RANGE( uStartPage, uMinPage, uMaxPage ) )
{
lpProcessSeg->lpdwSecondPageTable[uStartPage] = uiPhyPage;
}
//
break;
}
WARNMSG( DEBUG_SEG_MAPPHYPAGES, ("Seg_MapPhyPages, entry sleep.\r\n" ) );
Sleep(200);
}
if( uiPhyPage == 0 )
{ // 不应该发生,某些错误!
ERRORMSG( DEBUG_SEG_MAPPHYPAGES, ( "error in Seg_MapPhyPages: fault error!, no enough phypage.\r\n" ) );
}
}
idxPageOffset++; // 块内的下一个页
iPages++;
uStartPage++;
}
idxPageOffset = 0;
}
//
// 我假定所有虚内存管理中的释放功能将会调用FlushCacheAndClearTLB功能,
// 所以我在分配功能里不调用FlushCacheAndClearTLB功能
// 这就是为什么我去掉了以下的代码
//if( bFlush )
// FlushCacheAndClearTLB();
return TRUE;
}
// ********************************************************************
// 声明:LPSEGMENT Seg_FindSegmentByIndex( UINT index )
// 参数:
// IN index - 段索引
// 返回值:
// 段结构指针
// 功能描述:
// 由段索引得到其所在的段
// 引用:
//
// ********************************************************************
LPSEGMENT Seg_FindSegmentByIndex( UINT index )
{
if( index < 64 )
{ // 用户空间 user space
if( lppProcessSegmentSlots[index] )
return (LPSEGMENT)lppProcessSegmentSlots[index]->lpSeg;
}
else
{ // 内核空间 0x80000000
if( index == KERNEL_SEGMENT_INDEX )
{
return InitKernelProcess.lpProcessSegments->lpSeg;
}
}
return NULL;
}
// ********************************************************************
// 声明:LPSEGMENT Seg_FindSegment( DWORD dwAddress )
// 参数:
// IN dwAddress - 虚地址
// 返回值:
// 段结构指针
// 功能描述:
// 由虚地址得到其所在的段
// 引用:
//
// ********************************************************************
#define DEBUG_SEG_FINDSEGMENT 0
static LPSEGMENT Seg_FindSegment( DWORD dwAddress )
{
return Seg_FindSegmentByIndex( GET_SEGMENT_INDEX( dwAddress ) );
}
// ********************************************************************
// 声明:LPPROCESS_SEGMENTS Seg_FindProcessSegment( DWORD dwAddress )
// 参数:
// IN dwAddress - 虚地址
// 返回值:
// 段结构指针
// 功能描述:
// 由虚地址得到其所在的段
// 引用:
//
// ********************************************************************
#define DEBUG_SEG_FINDSEGMENT 0
static LPPROCESS_SEGMENTS Seg_FindProcessSegment( DWORD dwAddress )
{
UINT index = GET_SEGMENT_INDEX( dwAddress );
if( index < 64 )
{ // 用户空间 user space
return lppProcessSegmentSlots[index];
}
else
{ // 内核空间 0x80000000
if( index == KERNEL_SEGMENT_INDEX )
{
return InitKernelProcess.lpProcessSegments;
}
}
return NULL;
}
// ********************************************************************
// 声明:BOOL Seg_Copy(
// LPPROCESS_SEGMENTS lpProcessSeg,
// LPSEGMENT lpSegDst,
// UINT idxDstStartBlk,
// UINT idxStartPage,
// DWORD dwCopyPages,
// LPSEGMENT lpSegSrc,
// UINT idxSrcStartBlk,
// DWORD dwProtect )
// 参数:
// IN lpProcessSeg - 进程段组
// IN lpSegDst - 目标段结构指针
// IN idxDstStartBlk - 目标段开始块
// IN idxStartPage - 目标段块内开始页
// IN dwCopyPages - 需要拷贝的页
// IN lpSegSrc - 源段结构指针
// IN idxSrcStartBlk - 源段开始块
// IN dwProtect - 保护属性
// 返回值:
// 假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 将源区域的物理页映射到目标区域
// 引用:
//
// ********************************************************************
BOOL Seg_Copy(
LPPROCESS_SEGMENTS lpProcessSeg,
LPSEGMENT lpSegDst,
UINT idxDstStartBlk,
UINT idxStartPage,
DWORD dwCopyPages,
LPSEGMENT lpSegSrc,
UINT idxSrcStartBlk,
DWORD dwProtect )
{
LPMEMBLOCK * lppDstBlks, * lppSrcBlks;
DWORD dwPhysAddrMask = GetPhyPageAdrMask();
BOOL bWriteToSecondPage;
UINT uStartPage, uMinPage, uMaxPage;
dwProtect = GetAttribFromProtect( dwProtect );//得到CPU的属性
lppDstBlks = lpSegDst->lpBlks + idxDstStartBlk; // 开始目标块
lppSrcBlks = lpSegSrc->lpBlks + idxSrcStartBlk;//开始源块
//需要CACHE ?-2005-02-03, add
uMinPage = uStartPage = idxDstStartBlk * PAGES_PER_BLOCK + idxStartPage;
uMaxPage = uStartPage + dwCopyPages;
bWriteToSecondPage = GetPagesInCacheRange( lpProcessSeg, &uMinPage, &uMaxPage );
//
while( dwCopyPages )
{
UINT * lpuiDstPage = &(*lppDstBlks)->uiPages[idxStartPage];//开始目标页
UINT * lpuiSrcPage = &(*lppSrcBlks)->uiPages[idxStartPage];//开始源页
lppDstBlks++; lppSrcBlks++;
while( idxStartPage < PAGES_PER_BLOCK &&
dwCopyPages )
{
DWORD dwPhy = *lpuiSrcPage & dwPhysAddrMask; //得到物理地址
// 拷贝
Page_Duplicate( (LPVOID)_GetVirtualPageAdr( dwPhy ) );
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -