《计算机操作系统》实验指导书 联系客服

发布时间 : 星期六 文章《计算机操作系统》实验指导书更新完毕开始阅读32c67cc3d5bbfd0a79567304

// 遍历整个虚拟内存并对用户显示其属性的工作程序的方法 void WalkVM(HANDLE hProcess) {

// 首先,获得系统信息 SYSTEM_INFO si;

:: ZeroMemory(&si, sizeof(si) ) ; :: GetSystemInfo(&si) ;

// 分配要存放信息的缓冲区

MEMORY_BASIC_INFORMATION mbi; :: ZeroMemory(&mbi, sizeof(mbi) ) ; // 循环整个应用程序地址空间

LPCVOID pBlock = (LPVOID) si.lpMinimumApplicationAddress; while (pBlock < si.lpMaximumApplicationAddress) {

// 获得下一个虚拟内存块的信息 if (:: VirtualQueryEx( hProcess, // 相关的进程 pBlock, // 开始位置 &mbi, // 缓冲区 sizeof(mbi))==sizeof(mbi) ) // 大小的确认 {

// 计算块的结尾及其大小

LPCVOID pEnd = (PBYTE) pBlock + mbi.RegionSize; TCHAR szSize[MAX_PATH];

:: StrFormatByteSize(mbi.RegionSize, szSize, MAX_PATH) ; // 显示块地址和大小 std :: cout.fill ('0') ; std :: cout

<< std :: hex << std :: setw(8) << (DWORD) pBlock << \

<< std :: hex << std :: setw(8) << (DWORD) pEnd << (:: strlen(szSize)==7? \

// 显示块的状态 switch(mbi.State) {

case MEM_COMMIT:

std :: cout << \break;

case MEM_FREE:

std :: cout << \break;

case MEM_RESERVE:

std :: cout << \break;

}

// 显示保护 if (mbi.Protect==0 && mbi.State!=MEM_FREE)

{

mbi.Protect=PAGE_READONLY; } ShowProtection(mbi.Protect);

// 显示类型

switch (mbi.Type)

{

case MEM_IMAGE:

std :: cout << \break;

case MEM_MAPPED:

std :: cout << \break;

case MEM_PRIVATE:

std :: cout << \break;

}

// 检验可执行的影像

TCHAR szFilename [MAX_PATH] ;

if ( :: GetModuleFileName ( (HMODULE) pBlock, // 实际虚拟内存的模块句柄 szFilename, // 完全指定的文件名称 MAX_PATH)>0) // 实际使用的缓冲区大小

{

// 除去路径并显示

:: PathStripPath(szFilename) ;

std :: cout << \ }

std :: cout << std :: endl; // 移动块指针以获得下一下个块 pBlock = pEnd; } }

}

void main() {

// 遍历当前进程的虚拟内存

::WalkVM(::GetCurrentProcess()); }

程序中显示一个WalkVM() 函数开始于某个进程可访问的最低端虚拟地址处,并在其中显示各块虚拟内存的特性。虚拟内存中的块由VirtualQueryEx() API定义成连续快或具有相同状态 (自由区、已调配区等等) 的内存,并分配以一组统一的保护标志 (只读、可执行等等) 。

分析运行结果

按committed、reserved、free等三种虚拟地址空间分别记录实验数据。其中“描述”是指对该组数据的简单描述,例如,对下列一组数据:

00010000 – 00012000 <8.00KB> Committed, READWRITE, Private 可描述为:具有READWRITE权限的已调配私有内存区。

将系统当前的自由区 (free) 虚拟地址空间填入表中。

地址 大小 虚拟地址 空间类型 free free free free free 访问权限 描述

将系统当前的已调配区 (committed) 虚拟地址空间填入表中。 地址 大小 虚拟地址 空间类型 committed committed committed committed committed 访问权限 描述

将系统当前的保留区 (reserved) 虚拟地址空间填入表5-8中。 地址 大小 虚拟地址 空间类型 reserved 访问权限 描述 reserved reserved reserved reserved

2) 从上述输出结果,对照分析程序,请简单描述程序运行的流程:

____________________________________________________________________ ________________________________________________________________________ 2. 虚拟内存操作

示例程序显示了如何分配一个大容量空间,将物理存储委托给其中的很小一部分 (千分之一) 并加以使用。

分配和使用大块内存

// 工程largealloc

# include # include

// 尝试以指定长度的零数字填充内存块的简便方法 void FillZero(LPVOID pBlock, DWORD dwSize) {

_try {

BYTE* arFill = (BYTE *) pBlock;

for (DWORD dwFill = 0; dwFill < dwSize; ++dwFill) {

arFill [dwFill] = 0; }

std :: cout << “Memory zeroed.” << std :: endl; }

_except(EXCEPTION_EXECUTE_HANDLER) {

std :: cout << “Could not zero memory. ” << std :: endl; }

}

void main() {

// 简单的常数

DWORD c_dwGigabyte = 1 << 30; DWORD c_dwMegabyte = 1 << 20; // 使用内存分配来获得1GB块 {

LPVOID pBlock = :: malloc(c_dwGigabyte) ; :: FillZero (pBlock, c_dwMegabyte) ; :: free(pBlock) ; }

// 使用虚拟分配以获得物理1GB块 {

LPVOID pBlock = :: VirtualAlloc( NULL, // 不指定起始地址 c_dwGigabyte, // 要求1GB MEM_COMMIT, // 调配物理存储 PAGE_READWRITE) ; // 对此的读写操作 :: FillZero(pBlock, c_dwMegabyte) ;

:: VirtualFree(pBlock, 0, MEM_RELEASE) ; }

// 使用虚拟分配以获得虚拟1GB块 {

LPVOID pBlock = :: VirtualAlloc( NULL, // 不指定起始地址 c_dwGigabyte, // 要求1GB MEM_RESERVE, // 不调配物理存储 PAGE_READWRITE) ; // 对此的读写操作

:: FillZero(pBlock, c_dwMegabyte) ;

:: VirtualFree(pBlock, 0, MEM_RELEASE) ; }

// 使用虚拟分配调配获得虚拟1GB块,再为其调配1MB物理存储 {

LPVOID pBlock = :: VirtualAlloc( NULL, // 不指定起始地址 c_dwGigabyte, // 要求1GB MEM_RESERVE, // 不调配物理存储 PAGE_READWRITE) ; // 对此的读写操作 :: VirtualAlloc( pBlock,

c_dwMegabyte, MEM_COMMIT,

PAGE_READWRITE) ;

:: FillZero(pBlock, c_dwMegabyte) ;

:: VirtualFree(pBlock, 0, MEM_RELEASE) ; } }

对照运行结果,分析程序。为了给数据库保留1GB的段地址空间,程序给出了内存分配的四种方法。

· 第一种技术

即程序中说明为___________________________________________________的程序段,该段程序试图利用标准C中的malloc() 函数,从已经已调配的小内存区获得内存。从运行结果看,这种技术成功了吗?_____________________。

· 第二种技术

即程序中说明为___________________________________________________的程序段,该段程序试图通过VirtualAlloc() ,然后利用物理备用内存将整个块分配到虚拟内存空间的任何位置。这种技术只对拥有1GB以上的RAM且都有换页文件的计算机可行。从运行结果看,这种技术成功了吗?_____________________。

· 第三种技术

即程序中说明为___________________________________________________的程序段,该段程序利用VirtualAlloc() ,如果函数成功,则获得大块内存,但不将任何物理内存调配到此块中。从运行结果看,这种技术成功了吗?_________________。

· 第四种技术

即程序中说明为___________________________________________________的程序段,该段程序保留1GB的内存区,然后将物理内存调配给其中的很小一部分 (1MB) 。这就是程序介绍的处理一个假想的数据库应用程序的方法:保留整个块,然后按要求在其一小部分内进行读操作,让系统将用过的区域换页到磁盘中。

利用VirtualLock() API,Windows可用来在自己的进程空间中控制虚拟内存的行为。这个函数与其成对的VirtualUnlock() 阻止或允许一块内存从物理RAM中换页和换页到页面文件中。这样就会通知系统有一段特定的内存区要求对用户作出强烈的响应,所以系统不应将其移出RAM。当然,如果要将整个虚拟内存空间锁定,系统就会停留于试图将系统中工作内存的每一小块换页到磁盘

四、实验总结

请总结一下本次实验的收获、教训和感受,结合课本相关内容谈一下你对Windows 2000内存管理的理解。