2024年1月18日发(作者:)
五、源程序(含注释)清单
#include
#include
#include
#include
unsigned _stdcall simulator(void *);
unsigned _stdcall inspector(void *);
LPVOID BASE_PTR;
int Actnum=0;
//主函数,主要是用于启动用于模拟虚存活动和进行监控的两个线程;
int main(int argc, char* argv[])
{
unsigned ThreadID[2];
_beginthreadex(NULL,0,simulator,NULL,0,&ThreadID[0]);
_beginthreadex(NULL,0,inspector,NULL,0,&ThreadID[1]);
getchar();//输入回车即可终止程序;
return 0;
}
//模拟一系列的虚存活动,作为一个独立的线程运行;
unsigned _stdcall simulator(void *)
{
DWORD OldProtect;
int randnum;
printf("Now the simulator procedure has been started.n");
//产生一个随机数种子;
srand( (unsigned)time( NULL ) );
//在一个死循环中,用随机数控制,不断进行虚存操作活动;
while(1)
{
Sleep(500);//控制整个模拟和监控的速度;
while (Actnum!=0)
{
Sleep(500);//等待,直到监控线程捕捉到上一个模拟动作后再继续下一个动作;
}
randnum=7&rand();
switch(randnum)//注意各个动作中的虚存指针均使用BASE_PTR;它在过程中由虚存分配
//函数动态调整,如果某动作不成功,则将不会被监控线程监控到;
{
case 0:
if (BASE_PTR=VirtualAlloc(NULL,1024*32,MEM_RESERVE|MEM_COMMIT,
PAGE_READWRITE))
{
Actnum=1;//虚存的保留与提交;
}
break;
case 1:
if (VirtualFree(BASE_PTR,1024*32,MEM_DECOMMIT))
{
Actnum=2;//虚存的注销;
}
break;
case 2:
if (VirtualFree(BASE_PTR,0,MEM_RELEASE))
{
Actnum=3;//虚存的注销并释放虚存空间;
}
break;
case 3:
if (VirtualProtect(BASE_PTR,1024*32,PAGE_READONLY,&OldProtect))
{
Actnum=4;//改变虚拟内存页的保护;
}
break;
case 4:
if (VirtualLock(BASE_PTR,1024*12))
{
Actnum=5;//锁定虚拟内存页;
}
break;
case 5:
if
(BASE_PTR=VirtualAlloc(NULL,1024*32,MEM_RESERVE,PAGE_READWRITE))
{
Actnum=6;//虚存的保留;
}
break;
default:
break;
}//end of 'switch'
}//end of 'while'
return 0;
}
//通过一个全局的变量来监视另一模拟线程的模拟活动,并通过适当的信息
//查询函数,将存储的使用和活动情况打出报告;
unsigned _stdcall inspector(void *)
{
int QuOut=0;
char para1[3000];
MEMORYSTATUS Vmeminfo;
char tempstr[100];
MEMORY_BASIC_INFORMATION inspectorinfo1;
int structsize = sizeof(MEMORY_BASIC_INFORMATION);
printf("Hi , now inspector begin to workn");
//在一个死循环中不断通过一个全局变量(监视器),来监控模拟线程是否
//有新的动作,如果有,通过的API函数将相应虚存处(通过共用BASE_PTR
//实现)的信息进行检查,从而验证该动作对存储使用的影响;
while(1)
{
Sleep(1000);
if(Actnum!=0)
{
//通过全局变量(监视器)Actnum,来获取上一个虚存动作的类型
//并相应构造监控信息的头部;
switch(Actnum)
{
case 1:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:虚存的保留与提交n");
break;
case 2:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:虚存的除配n");
break;
case 3:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:虚存的除配并释放虚存空间n");
break;
case 4:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:改变虚拟内存页的保护n");
break;
case 5:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:锁定虚拟内存页n");
break;
case 6:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:虚存的保留n");
break;
default:
break;
}
//实时显示固定格式的相关材料;通过目前监控到的动作所发生
//的虚存地址,监控该活动对相应存储空间的影响;
sprintf(tempstr,"开始地址:0X%xn",dress);
strcat(para1,tempstr);
sprintf(tempstr,"区块大小(目前指针处向前同一属性的块):0X%xn",
Size);
strcat(para1,tempstr);
sprintf(tempstr,"目前状态:0X%xn",);
strcat(para1,tempstr);
sprintf(tempstr,"分配时访问保护:0X%xn",tionProtect);
strcat(para1,tempstr);
sprintf(tempstr,"当前访问保护:0X%xn",t);
strcat(para1,tempstr);
strcat(para1,"(状态:10000代表未分配 ;1000代表提交 ;2000代表保留; )n");
strcat(para1,"(保护方式:0代表其它;1代表禁止访问;2代表只读;4代表读写;n10代表可执");
strcat(para1," 行;20代表可读和执行; 40代表可读写和执行;)n*******************n");
//全局信息,报告目前系统和当前进程的存储使用总体情况;
GlobalMemoryStatus(&Vmeminfo);
strcat(para1,"当前整体存储统计如下n");
sprintf(tempstr,"物理内存总数:%d(BYTES)n",lPhys);
strcat(para1,tempstr);
sprintf(tempstr,"可用物理内存数:%d(BYTES)n",lPhys);
strcat(para1,tempstr);
sprintf(tempstr,"页面文件总数:%d(BYTES)n",lPageFile);
strcat(para1,tempstr);
sprintf(tempstr,"可用页面文件数:%d(BYTES)n",lPageFile);
strcat(para1,tempstr);
sprintf(tempstr,"虚存空间总数:%d(BYTES)n",lVirtual);
strcat(para1,tempstr);
sprintf(tempstr,"可用虚存空间数:%d(BYTES)n",lVirtual);
strcat(para1,tempstr);
sprintf(tempstr,"物理存储使用负荷:%%%dnnnn",ryLoad);
strcat(para1,tempstr);
printf("%s",para1);//显示报告内容
//(这里可以同时将报告内容记录进日志文件);
Actnum=0;//通知模拟线程可以进行下一个模拟动作;
Sleep(500);//调节模拟和监控的总体速度;
}//for if
}//for while
return 0;
}
六、测试结果以及实验总结
问答题:
1、如果调换分配、回收、内存复位、加锁、解锁、提交的顺序,会有什么变化,分析原因?
答:会造成用户程序和非常驻的系统程序无法正常存储于存储器中,从而无法运行。程序在计算机内必须进入主存中才能正常运行,当其要装入主存时,首先要为安分配一个适合的存储空间。若调换上述操作的顺序,则不能有效的把程序存入主存中。且计算机内的存储空间都是有限的,只有进行了分配、回收、复位的操作后,存储空间才能被循环利用,系统才能不断的运行不同的程序,不能把操作的顺序调换。
2、虚拟存储有什么优越性?
答:(1)虚拟存储可以大大提高存储系统的整体访问带宽,这也是其对于视频网络系统来说最有价值的一个特点。视频网络的存储系统一般是由多个存储模块组成,而虚拟存储系统可以很好地进行负载平衡,把每一次数据访问所需要的带宽合理地分配到各个存储模块上,这样系统的整体访问带宽就增大了。例如,一个存储系统中有4个存储模块,每一个存储模块的访问带宽为50MB/s,则这个存储系统的总访问带宽就可以接近各存储模块带宽之和,即200MB/s。(2)虚拟存储提供了一个大容量存储系统的集中管理手段,由网络中的一个环节 (如服务器)进行统一管理,避免了由于存储设备扩充而带来的管理方面的麻烦。例如,使用一般的存储系统,当在增加新的存储设备时,整个系统(包括网络中的诸多用户设备)都需要重新进行繁琐的配置工作,这样才可以使这个"新成员"加入到存储系统中。而使用虚拟存储技术,在增加新的存储设备时,只需要网络管理员对存储系统进行较为简单的系统配置更改,客户端无需任何操作、只是感到存储系统的容量增大了。(3)虚拟存储技术为存储资源管理提供了更好的灵活性。它可以将不同类型的存储设备集中管理使用,保障了用户以往购买存储设备的投资。
(3)相关函数及其属性的含义。
Beginthreadex
函数功能:创建新线程
函数原型:unsigned long _beginthreadex
返回值:0
Sleep
函数功能:对于指定的时间间隔挂起当前的执行线
函数原型:VOID Sleep(DWORD dwMilliseconds);
返回值:无
VirtualAlloc
函数功能:在调用进程的虚拟地址中保留、提交或保留且提交内存区域。
函数原型: LPVOID VirtualAlloc (LPVOID lpAddress, DWORD dwSize,
DWORD
flAllocationType, DWORD flProtect);
函数参数:
lpAddress:待分配空间的起始地址。若指定的内存被保留,指定的地址将四舍五入到下一个
64K边界;若指定的内存被保留且被提交,指定的地址将四舍五入到下一个页面边界。若为
NULL,则由系统决定分配区域的地址。
dwSize:分配空间的大小(以字节为单位) 。
flAllocationType:MEM_COMMIT 或MEM_RESERVE 或两者的组合
flProtect:存取保护的类型(参考测试数据的说明部分) 。
返回值:调用成功则返回所分配页面的基址,否则返回NULL。
VirtualFree
函数功能:释放或注销调用进程虚拟空间中的页面。在本实验中通过指定
dw
ype,对内存块进行释放(MEM_DECOMMIT)或者回收(MEM_RELEASE)的操作。
函数原型:
BOOL VirtualFree (LPVOID lpAddress, DWORD dwSize, DWORD
dwFreeType);
函数参数:
lpAddress:待释放空间的起始地址。若 dwFreeType 参数中包含
MEM_RELE
该页面被保留时,这个参数必须是通过VirtualAlloc函数返回的基址。
dwSize:释放空间的大小(以字节为单位) 。若 dwFreeType参数中包含
MEM
志,该参数值必须为 0。
dwFreeType:释放类型,可以是 MEM_DECOMMIT 或 MEM_RELEASE。
返回值:调用成功则返回一个非零值,否则返回 0。
VirtualProtect
函数功能:改变虚拟内存页的保护方式
HRESULT VirtualProtect (
[in] void* lpAddress,
[in] SIZE_T dwSize,
[in] DWORD flNewProtect,
[out] DWORD* pflOldProtect
);
参数:
lpAddress [in] 一个指针,指向要更保护属性的虚拟内存的基址。
dwSize [in] 要更改的内存页面区域的大小(以字节为单位)。
flNewProtect [in] 要应用的内存保护的类型。
pflOldProtect [out] 一个指针,该指针指向前一个内存保护值。
VirtualLock和VirtualUnlock
VirtualLock
函数功能:将调用进程虚拟空间中的内存加锁。
函数原型:BOOL VirtualLock (LPVOID lpAddress, DWORD dwSize);
函数参数:
lpAddress:加锁页面区域基址。
dwSize:加锁区域的大小(以字节为单位) 。
返回值:调用成功则返回一个非零值,否则返回 0
VirtualUnlock
函数功能:将调用进程虚拟空间中的内存解锁。
函数原型:BOOL VirtualUnlock (LPVOID lpAddress, DWORD dwSize);
函数参数:
lpAddress:解锁页面区域基址。
dwSize:解锁区域的大小(以字节为单位) 。
返回值:调用成功则返回一个非零值,否则返回 0。
VirtualQuery
函数功能:查询进程的虚拟内存
HRESULT VirtualQuery (
[in] void* lpAddress,
[out] void* lpBuffer,
[in] SIZE_T dwLength,
[out] SIZE_T* pResult
);
函数参数:
lpAddress [in] 一个指针,指向要查询的虚拟内存中的地址。
lpBuffer [out] 一个指针,指向包含指定内存区域相关信息的结构。
dwLength [in] lpBuffer 指向的缓冲区的大小(以字节为单位)。
pResult [out] 一个指针,它指向信息缓冲区返回的字节数。
GlobalMemoryStatus
函数功能:获得计算机系统中当前使用的物理内存和虚拟内存的信息
函数原型:VOID GlobalMemoryStatus (LPMEMORYSTATUS lpBuffer);
函数参数:lpBuffer是指向MEMORYSTATUS 结构的指针,_MEMORYSTATUS结构用来存
储系统内存信息,
返回值:无(在结构变量中)
成绩
VC++ (.NET 2010)
// : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
#include
#include
unsigned _stdcall simulator(void *);
unsigned _stdcall inspector(void *);
LPVOID BASE_PTR;
int Actnum=0;
//主函数,主要是用于启动用于模拟虚存活动和进行监控的两个线程;
int main(int argc, char* argv[])
{
unsigned ThreadID[2];
_beginthreadex(NULL,0,simulator,NULL,0,&ThreadID[0]);
_beginthreadex(NULL,0,inspector,NULL,0,&ThreadID[1]);
getchar();//输入回车即可终止程序;
return 0;
}
//模拟一系列的虚存活动,作为一个独立的线程运行;
unsigned _stdcall simulator(void *)
{
DWORD OldProtect;
int randnum;
printf("Now the simulator procedure has been started.n");
//产生一个随机数种子;
srand( (unsigned)time( NULL ) );
//在一个死循环中,用随机数控制,不断进行虚存操作活动;
while(1)
{
Sleep(500);//控制整个模拟和监控的速度;
while (Actnum!=0)
{
Sleep(500);//等待,直到监控线程捕捉到上一个模拟动作后再继续下一个动作;
}
randnum=7&rand();
switch(randnum)//注意各个动作中的虚存指针均使用BASE_PTR;它在过程中由虚存分配
//函数动态调整,如果某动作不成功,则将不会被监控线程监控到;
{
case 0:
if (BASE_PTR=VirtualAlloc(NULL,1024*32,MEM_RESERVE|MEM_COMMIT,
PAGE_READWRITE))
{
Actnum=1;//虚存的保留与提交;
}
break;
case 1:
if (VirtualFree(BASE_PTR,1024*32,MEM_DECOMMIT))
{
Actnum=2;//虚存的注销;
}
break;
case 2:
if (VirtualFree(BASE_PTR,0,MEM_RELEASE))
{
Actnum=3;//虚存的注销并释放虚存空间;
}
break;
case 3:
if (VirtualProtect(BASE_PTR,1024*32,PAGE_READONLY,&OldProtect))
{
Actnum=4;//改变虚拟内存页的保护;
}
break;
case 4:
if (VirtualLock(BASE_PTR,1024*12))
{
Actnum=5;//锁定虚拟内存页;
}
break;
case 5:
if (BASE_PTR=VirtualAlloc(NULL,1024*32,MEM_RESERVE,PAGE_READWRITE))
{
Actnum=6;//虚存的保留;
}
break;
break;
default:
}//end of 'switch'
}//end of 'while'
return 0;
}
//通过一个全局的变量来监视另一模拟线程的模拟活动,并通过适当的信息
//查询函数,将存储的使用和活动情况打出报告;
unsigned _stdcall inspector(void *)
{
int QuOut=0;
char para1[3000];
MEMORYSTATUS Vmeminfo;
char tempstr[100];
MEMORY_BASIC_INFORMATION inspectorinfo1;
int structsize = sizeof(MEMORY_BASIC_INFORMATION);
printf("Hi , now inspector begin to workn");
//在一个死循环中不断通过一个全局变量(监视器),来监控模拟线程是否
//有新的动作,如果有,通过的API函数将相应虚存处(通过共用BASE_PTR
//实现)的信息进行检查,从而验证该动作对存储使用的影响;
while(1)
{
Sleep(1000);
if(Actnum!=0)
{
//通过全局变量(监视器)Actnum,来获取上一个虚存动作的类型
//并相应构造监控信息的头部;
switch(Actnum)
{
case 1:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:虚存的保留与提交n");
break;
case 2:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:虚存的除配n");
break;
case 3:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:虚存的除配并释放虚存空间n");
break;
case 4:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:改变虚拟内存页的保护n");
break;
case 5:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:锁定虚拟内存页n");
break;
case 6:
memset (&inspectorinfo1, 0, structsize);
VirtualQuery((LPVOID)BASE_PTR,&inspectorinfo1,structsize);
strcpy(para1,"目前执行动作:虚存的保留n");
break;
default:
break;
}
//实时显示固定格式的相关材料;通过目前监控到的动作所发生
//的虚存地址,监控该活动对相应存储空间的影响;
sprintf(tempstr,"开始地址:0X%xn",dress);
strcat(para1,tempstr);
sprintf(tempstr,"区块大小(目前指针处向前同一属性的块):0X%xn",
Size);
strcat(para1,tempstr);
sprintf(tempstr,"目前状态:0X%xn",);
strcat(para1,tempstr);
sprintf(tempstr,"分配时访问保护:0X%xn",tionProtect);
strcat(para1,tempstr);
sprintf(tempstr,"当前访问保护:0X%xn",t);
strcat(para1,tempstr);
strcat(para1,"(状态:10000代表未分配 ;1000代表提交 ;2000代表保留; )n");
strcat(para1,"(保护方式:0代表其它;1代表禁止访问;2代表只读;4代表读写;n10代表可执");
strcat(para1," 行;20代表可读和执行; 40代表可读写和执行;)n*******************n");
//全局信息,报告目前系统和当前进程的存储使用总体情况;
GlobalMemoryStatus(&Vmeminfo);
strcat(para1,"当前整体存储统计如下n");
sprintf(tempstr,"物理内存总数:%d(BYTES)n",lPhys);
strcat(para1,tempstr);
sprintf(tempstr,"可用物理内存数:%d(BYTES)n",lPhys);
strcat(para1,tempstr);
sprintf(tempstr,"页面文件总数:%d(BYTES)n",lPageFile);
strcat(para1,tempstr);
sprintf(tempstr,"可用页面文件数:%d(BYTES)n",lPageFile);
strcat(para1,tempstr);
sprintf(tempstr,"虚存空间总数:%d(BYTES)n",lVirtual);
strcat(para1,tempstr);
sprintf(tempstr,"可用虚存空间数:%d(BYTES)n",lVirtual);
strcat(para1,tempstr);
sprintf(tempstr,"物理存储使用负荷:%%%dnnnn",ryLoad);
strcat(para1,tempstr);
printf("%s",para1);//显示报告内容
//(这里可以同时将报告内容记录进日志文件);
Actnum=0;//通知模拟线程可以进行下一个模拟动作;
Sleep(500);//调节模拟和监控的总体速度;
}//for if
}//for while
return 0;
}
发布评论