实验3虚拟存储器.docx
《实验3虚拟存储器.docx》由会员分享,可在线阅读,更多相关《实验3虚拟存储器.docx(26页珍藏版)》请在冰豆网上搜索。
实验3虚拟存储器
实验3、Windows虚拟内存
(一)、虚拟内存
1背景知识
在Windows环境下,32位Windows系统中,232=4GB的虚拟地址空间被划分成两个部分:
低端2GB提供给进程使用,高端2GB提供给系统使用。
这意味着用户的应用程序代码,包括DLL以及进程使用的各种数据等,都装在用户进程地址空间内(低端2GB)。
用户过程的虚拟地址空间也被分成三部分:
1)虚拟内存的已调配区(committed):
具有备用的物理内存,根据该区域设定的访问权限,用户可以进行写、读或在其中执行程序等操作。
2)虚拟内存的保留区(reserved):
没有备用的物理内存,但有一定的访问权限o
3)虚拟内存的自由区(free):
不限定其用途,有相应的PAGE_NOACCESS权限。
与虚拟内存区相关的访问权限告知系统进程可在内存中进行何种类型的操作。
例如,用户不能在只有PAGE_READONLY权限的区域上进行写操作或执行程序;也不能在只有PAGE_EXECUTE权限的区域里进行读、写操作。
而具有PAGE_NOACCESS权限的特殊区域,则意味着不允许进程对其地址进行任何操作。
在进程装入之前,整个虚拟内存的地址空间都被设置为只有PAGE_NOACCESS权限的自由区域。
当系统装入进程代码和数据后,才将内存地址的空间标记为已调配区或保留区,并将诸如EXECUTE、READWRITE和READONLY的权限与这些区域相关联。
如表1所示,给出了MEMORY_BASIC_INFORMATION的结构,此数据描述了进程虚拟内存空间中一组虚拟内存页面的当前状态,其中State项表明这些区域是否为自由区、已调配区或保留区;Protect项则包含了Windows系统为这些区域添加了何种访问保护;Type项则表明这些区域是可执行图像、内存映射文件还是简单的私有内存。
VirtualQueryEX()API能让用户在指定的进程中,对虚拟内存地址的大小和属性进行检测。
Windows还提供了一整套能使用户精确控制应用程序的虚拟地址空间的虚拟内存API。
一些用于虚拟内存操作及检测的API如表2所示。
表1MEMORY_BASIC_INFORMATION结构的成员
成员名称
目的
PVOIDBaseAddress
虚拟内存区域开始处的指针
PVOIDAllocationBase
如果这个特定的区域为子分配区的话,则为虚拟内存外面区域的指针;否则,此值与BaseAddress相同
DWORDAllocationProtect
虚拟内存最初分配区域的保护属性。
其可能值包括:
PAGE_NOACCESS,PAGE_READONLY,PAGE_READWRITE和PAGE_EXECUTE_READ
DWORDRegionSize
虚拟内存区域的字节数
DWORDState
区域的当前分配状态。
其可能值为MEM_COMMIT,MEM_FREE和MEM_RESERVE
DW()RDProtect
虚拟内存当前区域的保护属性。
可能值与AllocationProtect成员的相同
DWORDType
虚拟内存区域中出现的页面类型。
可能值为MEM_IMAGE,MEM_MAPPED和MEM_PRIVATE
表2虚拟内存的API
APl名称
描述
VirtualQueryEx()
通过填充MEMORY_BASIC_INFORMATION结构检测进程内虚拟内存的区域
VirtuaAlloc()
保留或调配进程的部分虚拟内存,设置分配和保护标志
VirtualFree()
释放或收回应用程序使用的部分虚拟地址
VirtualProtect()
改变虚拟内存区域保护规范
VirtualLock()
防止系统将虚拟内存区域通过系统交换到页面文件中
VirtualUnlock()
释放虚拟内存的锁定区域,必要时,允许系统将其交换到页面文件中
提供虚拟内存分配功能的是VinualAlloc()API。
该API支持用户向系统要求新的虚拟内存或改变已分配内存的当前状态。
用户若想通过VirtualAlloc()函数使用虚拟内存,可以采用两种方式通知系统:
1)简单地将内存内容保存在地址空间内。
2)请求系统返回带有物理存储区(RAM的空间或换页文件)的部分地址空间。
用户可以用flAllocationType参数(commit和reserve)来定义这些方式,用户可以通知Windows按只读、读写、不可读写、执行或特殊方式来处理新的虚拟内存。
与VirtualAlloc()函数对应的是VirtualFree()函数,其作用是释放虚拟内存中的已调配页或保留页。
用户可利用dwFreeType参数将已调配页修改成保留页属性。
VirtualProtect()是VirtualAlloc()的一个辅助函数,利用它可以改变虚拟内存区的保护规范。
2实验目的
1)通过实验了解Windows内存的使用,学习如何在应用程序中管理内存,体会Windows应用程序内存的简单性和自我防护能力。
2)学习检查虚拟内存空间或对其进行操作。
3)了解Windows的内存结构和虚拟内存的管理,进而了解进程堆和Windows为使用内存而提供的一些扩展功能。
3实验内容与步骤
虚拟内存的检测
清单2所示的程序使用VirtualQueryEX()函数来检查虚拟内存空间。
步骤1:
在“开始”菜单中单击“程序”、“MicrosoftVisualStudio6.0”、
“MicrosoftVisualC++6.0”,进入VisualC++窗口。
步骤2:
运行以下程序清单
清单2检测进程的虚拟地址空间
#include
#include
#include
#include
#pragmacomment(lib,"shlwapi.lib")
//以可读方式对用户显示保护的辅助方法。
//保护标记表示允许应用程序对内存进行访问的类型以及操作系统强制访问的类型
inlineboolTestSet(DWORDdwTarget,DWORDdwMask)
{
return((dwTarget&dwMask)==dwMask);
}
#defineSHOWMASK(dwTarget,type)\
if(TestSet(dwTarget,PAGE_##type))\
{std:
:
cout<<","<<#type;}
voidShowProtection(DWORDdwTarget)
{
SHOWMASK(dwTarget,READONLY);
SHOWMASK(dwTarget,GUARD);
SHOWMASK(dwTarget,NOCACHE);
SHOWMASK(dwTarget,READWRITE);
SHOWMASK(dwTarget,WRITECOPY);
SHOWMASK(dwTarget,EXECUTE);
SHOWMASK(dwTarget,EXECUTE_READ);
SHOWMASK(dwTarget,EXECUTE_READWRITE);
SHOWMASK(dwTarget,EXECUTE_WRITECOPY);
SHOWMASK(dwTarget,NOACCESS);
}
//遍历整个虚拟内存并对用户显示其属性的工作程序的方法
voidWalkVM(HANDLEhProcess)
{
//首先,获得系统信息
SYSTEM_INFOsi;
:
:
ZeroMemory(&si,sizeof(si));
:
:
GetSystemInfo(&si);
//分配要存放信息的缓冲区
MEMORY_BASIC_INFORMATIONmbi;
:
:
ZeroMemory(&mbi,sizeof(mbi));
//循环整个应用程序地址空间
LPCVOIDpBlock=(LPVOID)si.lpMinimumApplicationAddress;
while(pBlock{
//获得下一个虚拟内存块的信息
if(:
:
VirtualQueryEx(
hProcess,//相关的进程
pBlock,//开始位置
&mbi,//缓冲区
sizeof(mbi))==sizeof(mbi))//大小的确认
{
//计算块的结尾及其大小
LPCVOIDpEnd=(PBYTE)pBlock+mbi.RegionSize;
TCHARszSize[MAX_PATH];
:
:
StrFormatByteSize(mbi.RegionSize,szSize,MAX_PATH);
//显示块地址和大小
std:
:
cout.fill('0');
std:
:
cout<:
hex<:
setw(8)<<(DWORD)pBlock<<"-"
<:
hex<:
setw(8)<<(DWORD)pEnd
<<(strlen(szSize)==7?
"(":
"(")<//显示块的状态
switch(mbi.State)
{
caseMEM_COMMIT:
std:
:
cout<<",Committed";
break;
caseMEM_FREE:
std:
:
cout<<",Free";
break;
caseMEM_RESERVE:
std:
:
cout<<",Reserved";
break;
}
//显示保护
if(mbi.Protect==0&&mbi.State!
=MEM_FREE)
{
mbi.Protect=PAGE_READONLY;
}
ShowProtection(mbi.Protect);
//显示类型
switch(mbi.Type)
{
caseMEM_IMAGE:
std:
:
cout<<",Image";
break;
caseMEM_MAPPED:
std:
:
cout<<",Mapped";
break;
caseMEM_PRIVATE:
std:
:
cout<<",Private";
break;
}
//检验可执行的影像
TCHARszFilename[MAX_PATH];
if(:
:
GetModuleFileName(
(HMODULE)pBlock,
szFilename,
MAX_PATH)>0)
{
//除去路径并显示
:
:
PathStripPath(szFilename);
std:
:
cout<<",Module:
"<}
std:
:
cout<:
endl;
//移动块指针以获得下一个块
pBlock=pEnd;
}
}
}
voidmain()
{
//遍历当前进程的虚拟内存
:
:
WalkVM(:
:
GetCurrentProcess());
}
清单2中显示一个WalkVM()函数开始于某个进程可访问的最低端虚拟地址处,并在其中显示各块虚拟内存的特性。
虚拟内存中的块由VirtualQueryEx()APl定义成连续块或具有相同状态(自由区、已调配区等)的内存,并分配以一组统一的保护标志(只读、可执行等)。
回答下列问题:
1)分析运行结果
committed、reserved、free分别表示什么含义?
答:
虚拟内存的已调配区、虚拟内存的保留区、虚拟内存的自由区
按committed、reserved、free等三种虚拟地址空间分别记录实验数据,其中“描述”是指对该组数据的简单描述,例如,对下列一组数据:
00010000—00012000<8.00KB>Committed,READWRITE,Private可描述为:
具有READWRITE权限的已调配私有内存区。
将系统当前的自由区(free)虚拟地址空间填入表1中。
(表格可以自己画,通过把运行结果复制到word中文字转换成表格)
表1实验记录
地址
大小
虚拟地址
空间类型
访问权限
描述(type)
00012000-00020000
56.0KB
free
NOACCESS
00021000-00030000
60.0KB
free
NOACCESS
00133000-00140000
52.0KB
free
NOACCESS
00276000-00280000
40.0KB
free
NOACCESS
002C1000-002D0000
60.0KB
free
NOACCESS
00311000-00320000
60.0KB
free
NOACCESS
00326000-00330000
40.0KB
free
NOACCESS
00371000-00380000
60.0KB
free
NOACCESS
00391000-003A0000
60.0KB
free
NOACCESS
0031A000-003B0000
60.0KB
free
NOACCESS
003C3000-003D0000
52.0KB
free
NOACCESS
003E0000-00400000
128KB
free
NOACCESS
00485000-00490000
44.0KB
free
NOACCESS
00558000=00560000
32.0KB
free
NOACCESS
00663000-00670000
52.0KB
free
NOACCCESS
00970000-62C20000
1.53GB
free
NOACCESS
62C29000-73FA0000
275MB
free
NOACCESS
1400B000-76300000
34.9MB
free
NOACCESS
7631D000-77BE0000
24.7MB
free
NOACCESS
77C38000-77D10000
864KB
free
NOACCESS
77E49000-77E51000
28.0KB
free
NOACCESS
77EE3000-77EF0000
52.0KB
free
NOACCESS
77F39000-77F40000
28.0KB
free
NOACCESS
77EE3000-77EF0000
52.0KB
free
NOACCESS
77F39000-77F40000
28.0KB
free
NOACCESS
将系统当前的已调配区(committed)虚拟地址空间填入表2中。
表2实验记录
地址
大小
虚拟地址
空间类型
访问权限
描述(type)
00010000-00012000
8.00KB
committed
READWRITE
Private
00020000-00021000
4.00KB
committed
READWRITE
Private
0012c000-0012d000
4.00KB
committed
GUARD,READWRITE
Private
0012d000-00130000
12.0KB
committed
READWRITE
Private
00130000-00133000
12.0KB
committed
READONLY
Mapped
00140000-00145000
20.0KB
committed
READWRITE
Private
00240000-00246000
24.0KB
committed
READWRITE
Private
00250000-00253000
12.0KB
committed
READWRITE
Mapped
00260000-00276000
88.0KB
committed
READONLY
Mapped
00280000-002c1000
260KB
committed
READONLY
Mapped
002d0000-00311000
260KB
committed
READONLY
Mapped
00320000-00326000
24.0KB
committed
READONLY
Mapped
00330000-00371000
260KB
committed
READONLY
Mapped
00380000-00388000
32.0KB
committed
READWRITE
Private
00390000-00391000
4.00KB
committed
READWRITE
Private
003a0000-003a1000
4.00KB
committed
READWRITE
Private
003b0000-003b4000
16.0KB
committed
READWRITE
Private
003c0000-003c3000
12.0KB
committed
READONLY
Mapped
003d0000-003d3000
12.0KB
committed
READWRITE
Private
00400000-00401000
4.00KB
committed
READONLY
Image,Module:
03.exe
00401000-00470000
444KB
committed
EXECUTE_READ
Image
00470000-00478000
32.0KB
committed
READONLY
Image
00478000-0047b000
12.0KB
committed
READWRITE
Image
0047b000-0047d000
8.00KB
committed
WRITECOPY
Image
0047d000-00481000
16.0KB
committed
READWRITE
Image
将系统当前的保留区(reserved)虚拟地址空间填入表3中。
表3实验记录
地址
大小
虚拟地址
空间类型
访问权限
描述(type)
00030000-0012c000
0.98MB
reserved
READONLY
Private
00145000-00240000
0.98MB
reserved
READONLY
Private
00246000-00250000
40.KB
reserved
READONLY
Private
00253000-00260000
52.0KB
reserved
READONLY
Mapped
00388000-00390000
32.0KB
reserved
READONLY
Private
003b4000-003c0000
48.0KB
reserved
READONLY
Private
003d3000-003e0000
52.0KB
reserved
READONLY
Private
00495000-00550000
748KB
reserved
READONLY
Mapped
00552000-00558000
24.0KB
reserved
READONLY
Mapped
006d5000-00970000
2.60MB
reserved
READONLY
Mapped
2)从上述输出结果,对照分析程序,请简单描述程序运行的流程:
答:
该程序,从主函数出发,调用voidWalkVM(HANDLEhProcess)函数,voidWalkVM(HANDLEhProcess)函数先得系统信息,再分配应用程序地址空间,接下来就是做循环函数内做循环:
首先每次获得下一个虚拟程序内存的信息——计算块的结尾及其大小,然后再显示块的大小与位置,及其状态,显示保护方式显示类型,检查可执行的影像—除去文件名的路径并将文件名显示出来——移动块指针以获得下一个块,从新做循环。
3)实验总结
(根据实验结果及自己查阅相关资料写出VirtualAlloc()函数的作用,各个参数的可能值及含义。
列出对虚拟内存的认识)
答:
通过本次实验,体会学习检查虚拟内存空间或对其进行操作,windows2000的内存采用,进而了解进程和windows为使用内存而提供的一些扩展功能。
虚拟内存是计算机系统内存管理的一种技术。
它使得应用成粗认为它拥有连续的可用的内存,而实际上,它通常是被隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。
virtualalloc是可以自己控制页面的保留,提交,释放的实际的。
实际上我们申请的内存没有使用的时候,都是被放在内存页面中,在使用的时候才会被切换到真正的物理存储器里。
可能的数值
含义
MEM_COMMIT为0x1000
分配指定保留的内存页的物理存储在内存或磁盘上的分页文件。
该函数的内存初始化为零。
保留并承诺在一个步骤的页面,调用VirtualAlloc的MEM_COMMIT|MEM_RESERVE。
该函数将失败,如果你尝试提交一个还没有被保留页。
由此产生的错误代码是ERROR_INVALID_ADDRESS。
尝试提交一个已经提交的页面不会导致函数失败。
这意味着你可以承诺不首先确定当前承诺在每一页的状态页面。
MEM_RESERVE0x2000
保留在没有任何实际的物理存储在内存或磁盘上的分页文件分配一个进程的虚拟地址空间的范围。
你可以提交保留页的后续调用VirtualAlloc的功能。
保留并承诺在一个步骤的页面,调用VirtualAlloc的MEM_COMMIT|MEM_RESERVE。
内存分配的功能,如其他的malloc和Lo