?? vmm.cpp
字號:
//***********************************************************************/
// Author : Garry
// Original Date : Aug,16 2005
// Module Name : VMM.CPP
// Module Funciton :
// This module countains virtual memory manager's implementation
// code.
// Last modified Author :
// Last modified Date :
// Last modified Content :
// 1.
// 2.
// Lines number :
//***********************************************************************/
#ifndef __STDAFX_H__
#include "..\INCLUDE\StdAfx.h"
#endif
//
//This routine is used to debug the virtual memory manager.
//It prints out all virtual areas the current memory manager has.
//
VOID PrintVirtualArea(__VIRTUAL_MEMORY_MANAGER* lpMemMgr)
{
BYTE strBuff[12];
__VIRTUAL_AREA_DESCRIPTOR* lpVad = NULL;
LPVOID lpAddr = NULL;
if(NULL == lpMemMgr)
return;
lpVad = lpMemMgr->lpListHdr;
PrintLine(" Virtuam memory manager's reserved area :");
while(lpVad)
{
PrintLine("---------------------");
//PrintLine((LPSTR)&lpVad->strName[0]);
lpAddr = lpVad->lpStartAddr;
Hex2Str((DWORD)lpAddr,strBuff);
PrintLine(strBuff);
lpAddr = lpVad->lpEndAddr;
Hex2Str((DWORD)lpAddr,strBuff);
PrintLine(strBuff);
lpVad = lpVad->lpNext;
}
PrintLine(" Finished to print out.");
}
//
//Declaration for member routines.
//
static LPVOID VirtualAlloc(__COMMON_OBJECT*,LPVOID,DWORD,DWORD,DWORD,UCHAR*,LPVOID);
static LPVOID GetPdAddress(__COMMON_OBJECT*);
static VOID VirtualFree(__COMMON_OBJECT*,LPVOID);
static VOID InsertIntoList(__COMMON_OBJECT*,__VIRTUAL_AREA_DESCRIPTOR*);
//
//The implementation of VmmInitialize routine.
//
BOOL VmmInitialize(__COMMON_OBJECT* lpThis)
{
__VIRTUAL_MEMORY_MANAGER* lpManager = NULL;
__PAGE_INDEX_MANAGER* lpPageIndexMgr = NULL;
__VIRTUAL_AREA_DESCRIPTOR* lpVad = NULL;
BOOL bResult = FALSE;
if(NULL == lpThis) //Parameter check.
return FALSE;
lpManager = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
lpManager->VirtualAlloc = VirtualAlloc;
lpManager->VirtualFree = VirtualFree;
lpManager->GetPdAddress = GetPdAddress;
lpManager->dwVirtualAreaNum = 0L;
//
//The following code creates the page index manager object.
//
lpPageIndexMgr = (__PAGE_INDEX_MANAGER*)ObjectManager.CreateObject(&ObjectManager,
NULL,
OBJECT_TYPE_PAGE_INDEX_MANAGER);
if(NULL == lpPageIndexMgr) //Failed to create the page index manager object.
{
goto __TERMINAL;
}
if(!lpPageIndexMgr->Initialize((__COMMON_OBJECT*)lpPageIndexMgr)) //Can not initialize.
{
ObjectManager.DestroyObject(&ObjectManager,
(__COMMON_OBJECT*)lpPageIndexMgr);
lpPageIndexMgr = NULL;
goto __TERMINAL;
}
lpManager->lpPageIndexMgr = lpPageIndexMgr;
lpVad = (__VIRTUAL_AREA_DESCRIPTOR*)KMemAlloc(sizeof(__VIRTUAL_AREA_DESCRIPTOR),
KMEM_SIZE_TYPE_ANY);
if(NULL == lpVad)
goto __TERMINAL;
#define SET(member,value) lpVad->member = value
SET(lpManager, lpManager);
SET(lpStartAddr, VIRTUAL_MEMORY_KERNEL_START);
SET(lpEndAddr, (LPVOID)VIRTUAL_MEMORY_KERNEL_END);
SET(lpNext, NULL);
SET(dwAccessFlags, VIRTUAL_AREA_ACCESS_RW);
SET(dwAllocFlags, VIRTUAL_AREA_ALLOCATE_COMMIT);
SET(lpLeft, NULL);
SET(lpRight, NULL);
SET(dwCacheFlags, VIRTUAL_AREA_CACHE_NORMAL);
#undef SET
__INIT_ATOMIC(lpVad->Reference);
StrCpy((LPSTR)"System Kernel",(LPSTR)&lpVad->strName[0]);
//
//Insert the system kernel area into virtual memory manager's list.
//
InsertIntoList((__COMMON_OBJECT*)lpManager,lpVad);
bResult = TRUE; //Commit the whole transaction.
__TERMINAL:
if(!bResult)
{
if(lpPageIndexMgr)
ObjectManager.DestroyObject(&ObjectManager,
(__COMMON_OBJECT*)lpPageIndexMgr); //Destroy the page index manager object.
if(lpVad)
KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0L); //Free memory.
return FALSE;
}
return TRUE;
}
//
//The implementation of VmmUninitialize routine.
//
VOID VmmUninitialize(__COMMON_OBJECT* lpThis)
{
__PAGE_INDEX_MANAGER* lpPageIndexMgr = NULL;
__VIRTUAL_MEMORY_MANAGER* lpManager = NULL;
__VIRTUAL_AREA_DESCRIPTOR* lpVad = NULL;
if(NULL == lpThis) //Parameter check.
return;
lpManager = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
//
//Here,we should delete all the virtual areas belong to this virtual memory manager.
//
lpPageIndexMgr = lpManager->lpPageIndexMgr;
if(lpPageIndexMgr) //Destroy the page index manager object.
{
ObjectManager.DestroyObject(&ObjectManager,
(__COMMON_OBJECT*)lpPageIndexMgr);
}
return;
}
//
//This macros is used to determin if a virtual address is within a virtual area.
//
#define WITHIN_VIRTUAL_AREA(lpAddr,lpVa) \
(((DWORD)((lpVa)->lpStartAddr) <= (DWORD)lpAddr) && \
((DWORD)((lpVa)->lpEndAddr) >= (DWORD)lpAddr))
//
//Check if a virtual memory address is between two virtual areas.
//
#define BETWEEN_VIRTUAL_AREA(lpAddr,lpVa1,lpVa2) \
(((DWORD)((lpVa1)->lpEndAddr) < (DWORD)lpAddr) && \
((DWORD)((lpVa2)->lpStartAddr) > (DWORD)lpAddr))
//
//Check if a virtual memory address is between two virtual addresses.
//
#define BETWEEN_VIRTUAL_ADDRESS(lpAddr,lpAddr1,lpAddr2) \
(((DWORD)lpAddr1 <= (DWORD)lpAddr) && \
((DWORD)lpAddr2 > (DWORD)lpAddr))
//
//SearchVirtualArea_l is a helper routine,used to search a proper virtual area in the
//Virtual Memory Space,the "l" menas it searchs in the virtual area list.
//CAUTION: This routine is not safe,it's the caller's responsibility to guarantee the
//safety.
//
static LPVOID SearchVirtualArea_l(__COMMON_OBJECT* lpThis,LPVOID lpDesiredAddr,DWORD dwSize)
{
__VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
__VIRTUAL_AREA_DESCRIPTOR* lpVad = NULL;
LPVOID lpStartAddr = NULL;
LPVOID lpEndAddr = NULL;
LPVOID lpDesiredEnd = NULL;
LPVOID lpPotentialStart = NULL;
LPVOID lpPotentialEnd = NULL;
BOOL bFind = FALSE;
if((NULL == lpThis) || (0 == dwSize)) //Invalidate parameters.
return NULL;
lpVad = lpMemMgr->lpListHdr;
if(NULL == lpVad) //There is not any virtual area in the space.
return lpDesiredAddr; //Successfully.
lpEndAddr = lpVad->lpStartAddr;
lpDesiredEnd = (LPVOID)((DWORD)lpDesiredAddr + dwSize - 1);
//lpPotentialEnd = (LPVOID)((DWORD)lpPotentialStart + dwSize);
while(lpVad)
{
if(BETWEEN_VIRTUAL_ADDRESS(lpDesiredAddr,lpStartAddr,lpEndAddr) &&
BETWEEN_VIRTUAL_ADDRESS(lpDesiredEnd,lpStartAddr,lpEndAddr)) //Find one.
{
return lpDesiredAddr;
}
if(!bFind) //To check if the gap can statisfy the required size,
//that is,if the gap can be a potential virtual area.
{
lpPotentialStart = lpStartAddr;
lpPotentialEnd = (LPVOID)((DWORD)lpPotentialStart + dwSize - 1);
if(BETWEEN_VIRTUAL_ADDRESS(lpPotentialEnd,lpStartAddr,lpEndAddr))
//Find a VA statisfy the
//original required size.
bFind = TRUE; //Set potential address to NULL.
}
lpStartAddr = (LPVOID)((DWORD)lpVad->lpEndAddr + 1);
lpVad = lpVad->lpNext;
if(lpVad)
lpEndAddr = lpVad->lpStartAddr;
else
lpEndAddr = (LPVOID)VIRTUAL_MEMORY_END;
}
if(BETWEEN_VIRTUAL_ADDRESS(lpDesiredAddr,lpStartAddr,lpEndAddr) &&
BETWEEN_VIRTUAL_ADDRESS(lpDesiredEnd,lpStartAddr,lpEndAddr))
return lpDesiredAddr;
if(!bFind) //Have not find a potential address,so try the last once.
{
lpPotentialStart = lpStartAddr;
lpPotentialEnd = (LPVOID)((DWORD)(lpPotentialStart) + dwSize - 1);
if(BETWEEN_VIRTUAL_ADDRESS(lpPotentialEnd,lpStartAddr,lpEndAddr)) //Can statisfy.
return lpPotentialStart;
else
return NULL;
}
else //Have found a virtual area that statisfy the original request,though the start
//address not the original desired one.
{
return lpPotentialStart;
}
return NULL;
}
//
//SearchVirtualArea_t is a same routine as SearchVirtualArea_l,the difference is,this
//routine searchs in the AVL tree.
//
static LPVOID SearchVirtualArea_t(__COMMON_OBJECT* lpThis,LPVOID lpStartAddr,DWORD dwSize)
{
return NULL; //We will implement it in the future :-)
}
//
//InsertIntoList routine,this routine inserts a virtual area descriptor object into
//virtual area list.
//
static VOID InsertIntoList(__COMMON_OBJECT* lpThis,__VIRTUAL_AREA_DESCRIPTOR* lpVad)
{
__VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
DWORD dwFlags = 0L;
__VIRTUAL_AREA_DESCRIPTOR* lpFirst = NULL;
__VIRTUAL_AREA_DESCRIPTOR* lpSecond = NULL;
if((NULL == lpThis) || (NULL == lpVad)) //Invalidate parameters.
return;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
lpFirst = lpMemMgr->lpListHdr;
if(NULL == lpFirst) //There is not any element in the list.
{
lpMemMgr->lpListHdr = lpVad;
lpMemMgr->dwVirtualAreaNum ++; //Increment the reference counter.
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return;
}
lpSecond = lpFirst;
while(lpFirst)
{
if((DWORD)lpFirst->lpStartAddr > (DWORD)lpVad->lpStartAddr) //Find the proper position.
break;
lpSecond = lpFirst;
lpFirst = lpFirst->lpNext;
}
if(lpSecond == lpFirst) //Should be the first element in the list.
{
lpVad->lpNext = lpMemMgr->lpListHdr;
lpMemMgr->lpListHdr = lpVad;
lpMemMgr->dwVirtualAreaNum ++;
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return;
}
else //Should not be the first element.
{
lpVad->lpNext = lpSecond->lpNext;
lpSecond->lpNext = lpVad;
}
lpMemMgr->dwVirtualAreaNum ++; //Increment the virtual area's total number.
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
}
//
//InsertIntoTree routine,the same as above except that this routine is used to insert
//a virtual memory area into AVL tree.
//
static VOID InsertIntoTree(__COMMON_OBJECT* lpThis,__VIRTUAL_AREA_DESCRIPTOR* lpVad)
{
return; //We will implement this routine in the future. :-)
}
//
//A helper routine used to get a virtual area descriptor object by a virtual address.
//The label "l" means the search target is list.
//
static __VIRTUAL_AREA_DESCRIPTOR* GetVaByAddr_l(__COMMON_OBJECT* lpThis,LPVOID lpAddr)
{
__VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
__VIRTUAL_AREA_DESCRIPTOR* lpVad = NULL;
if((NULL == lpThis) || (NULL == lpAddr)) //Invalidate parameters.
return NULL;
lpVad = lpMemMgr->lpListHdr;
while(lpVad)
{
if(WITHIN_VIRTUAL_AREA(lpAddr,lpVad))
return lpVad;
lpVad = lpVad->lpNext;
}
return lpVad; //If can not search a proper VA,then NULL is returned.
}
//
//Get a virtual area descriptor object from AVL tree according to a virtual
//memory address.
//
static __VIRTUAL_AREA_DESCRIPTOR* GetVaByAddr_t(__COMMON_OBJECT* lpThis,LPVOID lpAddr)
{
return NULL; //We will complete this routine in the future. :-)
}
//
//DoCommit routine.When VirtualAlloc is called with VIRTUAL_AREA_ALLOCATE_COMMIT,
//then is routine is called by VirtualAlloc.
//
static LPVOID DoCommit(__COMMON_OBJECT* lpThis,
LPVOID lpDesiredAddr,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -