⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vmm.cpp

📁 小型的操作系统开发的原代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//***********************************************************************/
//    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 + -