实验九存储管理.docx

上传人:b****6 文档编号:12779819 上传时间:2023-06-08 格式:DOCX 页数:21 大小:46.60KB
下载 相关 举报
实验九存储管理.docx_第1页
第1页 / 共21页
实验九存储管理.docx_第2页
第2页 / 共21页
实验九存储管理.docx_第3页
第3页 / 共21页
实验九存储管理.docx_第4页
第4页 / 共21页
实验九存储管理.docx_第5页
第5页 / 共21页
实验九存储管理.docx_第6页
第6页 / 共21页
实验九存储管理.docx_第7页
第7页 / 共21页
实验九存储管理.docx_第8页
第8页 / 共21页
实验九存储管理.docx_第9页
第9页 / 共21页
实验九存储管理.docx_第10页
第10页 / 共21页
实验九存储管理.docx_第11页
第11页 / 共21页
实验九存储管理.docx_第12页
第12页 / 共21页
实验九存储管理.docx_第13页
第13页 / 共21页
实验九存储管理.docx_第14页
第14页 / 共21页
实验九存储管理.docx_第15页
第15页 / 共21页
实验九存储管理.docx_第16页
第16页 / 共21页
实验九存储管理.docx_第17页
第17页 / 共21页
实验九存储管理.docx_第18页
第18页 / 共21页
实验九存储管理.docx_第19页
第19页 / 共21页
实验九存储管理.docx_第20页
第20页 / 共21页
亲,该文档总共21页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

实验九存储管理.docx

《实验九存储管理.docx》由会员分享,可在线阅读,更多相关《实验九存储管理.docx(21页珍藏版)》请在冰点文库上搜索。

实验九存储管理.docx

实验九存储管理

实验九存储管理

[1]WindowsXp存结构

背景知识

WindowsXp是32位的操作系统,它使计算机CPU可以用32位地址对32位存块进行操作。

存中的每一个字节都可以用一个32位的指针来寻址。

这样,最大的存储空间就是232字节或4000兆字节(4GB)。

这样,在Windows下运行的每一个应用程序都认为能独占可能的4GB大小的空间

而另一方面,实际上没有几台机器的RAM能达到4GB,更不必说让每个进程都独享4GB存了。

Windows在幕后将虚拟存(virtualmemory,VM)地址映射到了各进程的物理存地址上。

而所谓物理存是指计算机的RAM和由Windows分配到用户驱动器根目录上的换页文件。

物理存完全由系统管理。

实验目的

1)通过实验了解windowsXp存的使用,学习如何在应用程序中管理存、体会Windows应用程序存的简单性和自我防护能力。

2)了解windowsXp的存结构和虚拟存的管理,进而了解进程堆和windows为使用存而提供的一些扩展功能。

工具/准备工作

您需要做以下准备:

一台运行WindowsXpProfessional操作系统的计算机

计算机中需安装VisualC++6.0专业版或企业版

实验容与步骤

Windows提供了一个API即GetSystemInfo(),以便用户能检查系统中虚拟存的一些特性。

程序5-1显示了如何调用该函数以及显示系统中当前存的参数。

步骤1:

登录进入WindowsXpProfessional。

步骤2:

在“开始”菜单中单击“程序”-“MicrosoftVisualStudio6.0”–“MicrosoftVisualC++6.0”命令,进入VisualC++窗口。

步骤3:

在工具栏单击“打开”按钮,在“打开”对话框中找到并打开实验源程序5-1.cpp。

程序5-1:

获取有关系统的存设置的信息

//工程vmeminfo

#include

#include

#include

#include

#pragmacomment(lib,"shlwapi.lib")

voidmain()

{

//首先,让我们获得系统信息

SYSTEM_INFOsi;

:

:

ZeroMemory(&si,sizeof(si));

:

:

GetSystemInfo(&si);

//使用外壳辅助程序对一些尺寸进行格式化

TCHARszPageSize[MAX_PATH];

:

:

StrFormatByteSize(si.dwPageSize,szPageSize,MAX_PATH);

DWORDdwMemSize=(DWORD)si.lpMaximumApplicationAddress-

(DWORD)si.lpMinimumApplicationAddress;

TCHARszMemSize[MAX_PATH];

:

:

StrFormatByteSize(dwMemSize,szMemSize,MAX_PATH);

//将存信息显示出来

std:

:

cout<<"Virtualmemorypagesize:

"<

:

endl;

std:

:

cout.fill('0');

std:

:

cout<<"Minimumapplicationaddress:

0x"

<

:

hex<

:

setw(8)

<<(DWORD)si.lpMinimumApplicationAddress

<

:

endl;

std:

:

cout<<"Maximumapplicationaddress:

0x"

<

:

hex<

:

setw(8)

<<(DWORD)si.lpMaximumApplicationAddress

<

:

endl;

std:

:

cout<<"Totalavailablevirtualmemory:

"

<

:

endl;

}

步骤4:

单击“Build”菜单中的“Compile5-1.cpp”命令,并单击“是”按钮确认。

系统对5-1.cpp进行编译。

步骤5:

编译完成后,单击“Build”菜单中的“Build5-1.exe”命令,建立5-1.exe可执行文件。

操作能否正常进行?

如果不行,则可能的原因是什么?

_不可以运行,#pragmacomment(lib,"shlwapi.lib")指令错误,在pragma与comment中间应该有空格___________________________________________________________________

________________________________________________________________________

步骤6:

在工具栏单击“ExecuteProgram”(执行程序)按钮,执行5-1.exe程序。

运行结果(分行书写。

如果运行不成功,则可能的原因是什么?

):

1)虚拟存每页容量为:

4.00KB

2)最小应用地址:

0*00010000

3)最大应用地址:

0*7ffeffff

4)当前可供应用程序使用的存空间为:

2.00GB

5)当前计算机的实际存大小为:

1.99GB

1)虚拟存每页容量为:

2)最小应用地址:

3)最大应用地址为:

4)当前可供应用程序使用的存空间为:

5)当前计算机的实际存大小为:

阅读和分析程序5-1,请回答问题:

1)理论上每个windows应用程序可以独占的最大存储空间是:

____4GB____

2)在程序5-1中,用于检索系统中虚拟存特性的API函数是:

DWORD

提示:

可供应用程序使用的存空间实际上已经减去了开头与结尾两个64KB的保护区。

虚拟存空间中的64KB保护区是防止编程错误的一种Windows方式。

任何对存中这一区域的访问(读、写、执行)都将引发一个错误陷井,从而导致错误并终止程序的执行。

也就是说,假如用户有一个NULL指针(地址为0),但仍试图在此之前很近的地址处使用另一个指针,这将因为试图从更低的保留区域读写数据,从而产生意外错误并终止程序的执行。

[2]WindowsXp虚拟存

背景知识

在WindowsXp环境下,4GB的虚拟地址空间被划分成两个部分:

低端2GB提供给进程使用,高端2GB提供给系统使用。

这意味着用户的应用程序代码,包括DLL以及进程使用的各种数据等,都装在用户进程地址空间(低端2GB)。

用户过程的虚拟地址空间也被分成三部分:

1)虚拟存的已调配区(committed):

具有备用的物理存,根据该区域设定的访问权限,用户可以进行写、读或在其中执行程序等操作。

2)虚拟存的保留区(reserved):

没有备用的物理存,但有一定的访问权限。

3)虚拟存的自由区(free):

不限定其用途,有相应的PAGE_NOACCESS权限。

与虚拟存区相关的访问权限告知系统进程可在存中进行何种类型的操作。

例如,用户不能在只有PAGE_READONLY权限的区域上进行写操作或执行程序;也不能在只有PAGE_EXECUTE权限的区域里进行读、写操作。

而具有PAGE_NOACCESS权限的特殊区域,则意味着不允许进程对其地址进行任何操作。

在进程装入之前,整个虚拟存的地址空间都被设置为只有PAGE_NOACCESS权限的自由区域。

当系统装入进程代码和数据后,才将存地址的空间标记为已调配区或保留区,并将诸如EXECUTE、READWRITE和READONLY的权限与这些区域相关联。

如表3-2所示,给出了MEMORY_BASIC_INFORMAITON的结构,此数据描述了进程虚拟存空间中的一组虚拟存页面的当前状态,期中State项表明这些区域是否为自由区、已调配区或保留区;Protect项则包含了windows系统为这些区域添加了何种访问保护;type项则表明这些区域是课执行图像、存映射文件还是简单的私有存。

VirsualQueryEX()API能让用户在指定的进程中,对虚拟存地址的大小和属性进行检测。

Windows还提供了一整套能使用户精确控制应用程序的虚拟地址空间的虚拟存API。

一些用于虚拟存操作及检测的API如表3-2所示。

表3-1MEMORY_BASIC_INFORMAITON结构的成员

成员名称

目的

PVOIDBaseAddress

虚拟存区域开始处的指针

PVOIDAllocationBase

如果这个特定的区域为子分配区的话,则为虚拟存外面区域的指针;否则此值与BaseAddress相同

DWORDAllocationProtect

虚拟存最初分配区域的保护属性。

其可能值包括:

PAGE_NOACCESS,PAGE_READONLY,PAGE_READWRITE和PAGE_EXECUTE_READ

DWORDRegionSize

虚拟存区域的字节数

DWORDState

区域的当前分配状态。

其可能值为MEM_COMMIT,MEM_PREE和MEM_RESERVE

DWORDProtect

虚拟存当前的保护属性。

可能值与AllocationProtect成员的相同

DWORDType

虚拟存区域中出现的页面类型。

可能值为MEM_IMAGE,MEM_MAPPED和MEM_PRIVATE

表3-2虚拟存的API

API名称

描述

VisualQueryEX()

通过填充MEMORY_BASIC_INFORMATION结构检测进程虚拟存的区域

VisualAlloc()

保留或调配进程的部分虚拟存,设置分配和保护标志

VirsualFree()

释放或收回应用程序使用的部分虚拟地址

VirsualProtect()

改变虚拟存区域保护规

VirsualLock()

防止系统将虚拟存区域通过系统交换到页面文件中

VirsualUnlock()

释放虚拟存的锁定区域,必要时,允许系统将其交换到页面文件中

提供虚拟存分配功能的是VirtualAlloc()API。

该API支持用户向系统要求新的虚拟存或改变已分配存的当前状态。

用户若想通过VirtualAlloc()函数使用虚拟存,可以采用两种方式通知系统:

1)简单地将存容保存在地址空间

2)请求系统返回带有物理存储区(RAM的空间或换页文件)的部分地址空间

用户可以用flAllocationType参数(commit和reserve)来定义这些方式,用户可以通知Windows按只读、读写、不可读写、执行或特殊方式来处理新的虚拟存。

与VirtualAlloc()函数对应的是VirtualFree()函数,其作用是释放虚拟存中的已调配页或保留页。

用户可利用dwFreeType参数将已调配页修改成保留页属性。

VirtualProtect()是VirtualAlloc()的一个辅助函数,利用它可以改变虚拟存区的保护规。

实验目的

1)通过实验了解WindowsXp存的使用,学习如何在应用程序中管理存,体会Windows应用程序存的简单性和自我防护能力。

2)学习检查虚拟存空间或对其进行操作。

3)了解WindowsXp的存结构和虚拟存的管理,进而了解进程堆和Windows为使用存而提供的一些扩展功能。

工具/准备工作

在开始本实验之前,请回顾教科书的相关容。

您需要做以下准备:

1)一台运行WindowsXpProfessional操作系统的计算机。

2)计算机中需安装VisualC++6.0专业版或企业版。

实验容与步骤

1.虚拟存的检测

清单5-2所示的程序使用VirtualQueryEX()函数来检查虚拟存空间。

步骤1:

登录进入WindowsXpProfessional。

步骤2:

在“开始”菜单中单击“程序”-“MicrosoftVisualStudio6.0”–“MicrosoftVisualC++6.0”命令,进入VisualC++窗口。

步骤3:

在工具栏单击“打开”按钮,在“打开”对话框中找到并打开实验源程序5-2.cpp。

清单5-2检测进程的虚拟地址空间

//工程vmwalker

#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());

}

清单5-2中显示一个walkVM()函数开始于某个进程可访问的最低端虚拟地址处,并在其中显示各块虚拟存的特性。

虚拟存中的块由VirsualQueryEX()API定义成连续快或具有相同状态(自由区,已调配区等)的存,并分配以一组统一的保护标志(只读、可执行等)。

步骤4:

单击“Build”菜单中的“Compile5-2.cpp”命令,并单击“是”按钮确认。

系统对5-2.cpp进行编译。

步骤5:

编译完成后,单击“Build”菜单中的“Build5-2.exe”命令,建立5-2.exe可执行文件。

操作能否正常进行?

如果不行,则可能的原因是什么?

___能运行_________________________________________________________________

________________________________________________________________________

步骤6:

在工具栏单击“ExecuteProgram”(执行程序)按钮,执行5-2.exe程序。

1)分析运行结果(如果运行不成功,则可能的原因是什么)

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

00010000-0001Xp<8.00KB>Committed,READWRITE,Private可描述为:

具有READWRITE权限的已调配私有存区。

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

地址

大小

虚拟地址

空间类型

访问权限

描述

 00010000-00012000

 8.00KB

free

 READWRITE

 具有READWRITE权限的已调配私有存区

 00012000-00020000

56.0KB

free

NOACCESS

 没有任何权限的已调配的共有存区

 00020000-00021000

 4.00KB

free

 READWRITE

 具有READWRITE权限的已调配私有存区

 00021000-00030000

 60.0KB

free

NOACCESS

 没有任何权限的已调配的共有存区

 00030000-0012c000

 0.98MB

free

  READONLY

  只具有READ权限的已调配私有存区

 0012c000-0012d000

 4.00KB

free

  READWRITE

  具有READWRITE权限的已调配私有存区

 0012d000-00130000

 12.0KB

free

 READWRITE

 具有READWRITE权限的已调配私有存区

 00130000-00133000

 12.0KB

free

 READONLY

   只具有READ权限的已调配存区

表3-3实验记录

地址

大小

虚拟空间类型

访问权限

描述

free

free

free

free

free

free

free

将系统当前的已调配区(Committed)虚拟地址空间填入表3-4中。

表3-4实验记录

00010000-00020000(64.0KB)Committed,READWRITE,Mapped

00020000-00030000(64.0KB)Committed,READWRITE,Mapped

0012d000-0012e000(4.00KB)Committed,GUARD,READWRITE,Private

0012e000-00130000(8.00KB)Committed,READWRITE,Private

00130000-00134000(16.0KB)Committed,READONLY,Mapped

00140000-001a7000(412KB)Committed,READONLY,Mapped

001b0000-001b1000(4.00KB)Com

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2