实验四内存监视.docx
《实验四内存监视.docx》由会员分享,可在线阅读,更多相关《实验四内存监视.docx(16页珍藏版)》请在冰点文库上搜索。
实验四内存监视
实验四:
内存监视
一、实验目的
了解当前系统中内存的使用情况,包括系统地址空间的布局,物理内存的使用情况;能实时显示某个进程的虚拟地址空间布局和工作集信息等。
二、实验内容
设计一个内存监视器,能实时地显示当前系统中内存的使用情况,包括系统地址空间的布局,物理内存的使用情况;能实时显示某个进程的虚拟地址空间布局和工作集信息等。
相关的系统调用:
GetSystemInfo,VirtualQueryEx,VirtualAlloc,GetPerformanceInfo,GlobalMemoryStatusEx...
三、实验环境
硬件配置:
联想IdeaPadY480笔记本。
内存4G,硬盘1T。
操作系统:
Windows7
四、程序设计与实现
打印出内存的相关信息,调用的函数有GetSystemInfo,VirtualQueryEx,VirtualAlloc,GetPerformanceInfo,GlobalMemoryStatusExt等。
五、实验代码、结果和分析
实验代码:
//实验四.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
//MemoryWatcher.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include"conio.h"
#pragmacomment(lib,"psapi.lib")
#pragmacomment(lib,"Shlwapi.lib")
#pragmawarning(disable:
4996)
usingnamespacestd;
#defineWIDTH10
#defineDIV(1024*1024)
//WINAPI得到当前console的(x,y)
voidconsole_gotoxy(intx,inty)
{
//得到当前console的句柄
HANDLEhc=GetStdHandle(STD_OUTPUT_HANDLE);
COORDcursor={x,y};
//设置新的cursor位置
SetConsoleCursorPosition(hc,cursor);
}
//WINAPI设置当前console的(x,y)
voidconsole_getxy(int&x,int&y)
{
//得到当前console的句柄
HANDLEhc=GetStdHandle(STD_OUTPUT_HANDLE);
//屏幕缓冲区信息
CONSOLE_SCREEN_BUFFER_INFOcsbi;
//得到相应缓冲区信息
GetConsoleScreenBufferInfo(hc,&csbi);
x=csbi.dwCursorPosition.X;
y=csbi.dwCursorPosition.Y;
}
HANDLEGetProcessHandle(intProcessID)
{
returnOpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessID);
}
//显示保护标记,该标记表示允许应用程序对内存进行访问的类型
inlineboolTestSet(DWORDdwTarget,DWORDdwMask)
{
return((dwTarget&dwMask)==dwMask);
}
#defineSHOWMASK(dwTarget,type)\
if(TestSet(dwTarget,PAGE_##type))\
{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))//长度的确认,如果失败则返回0
{
//块的结尾指针
LPCVOIDpEnd=(PBYTE)pBlock+mbi.RegionSize;
TCHARszSize[MAX_PATH];
StrFormatByteSize(mbi.RegionSize,szSize,MAX_PATH);
//显示块地址和长度
cout.fill('0');
cout<<<"--"
<<<(wcslen(szSize)==7?
"(":
"(")<<<")";
//显示块的状态
switch(mbi.State){
caseMEM_COMMIT:
printf("Committed");break;
caseMEM_FREE:
printf("Free");break;
caseMEM_RESERVE:
printf("Reserved");break;
}
//显示保护
if(mbi.Protect==0&&mbi.State!
=MEM_FREE){
mbi.Protect=PAGE_READONLY;
}
ShowProtection(mbi.Protect);
//显示类型
switch(mbi.Type){
caseMEM_IMAGE:
printf(",Image");break;
caseMEM_MAPPED:
printf(",Mapped");break;
caseMEM_PRIVATE:
printf(",Private");break;
}
//检测可执行的映像
TCHARszFilename[MAX_PATH];
if(GetModuleFileName(
(HMODULE)pBlock,//实际虚拟内存的模块句柄
szFilename,//完全指定的文件名称
MAX_PATH)>0)//实际使用的缓冲区长度
{
//除去路径并显示
PathStripPath(szFilename);
printf("%s",szFilename);
}
printf("\n");
//移动块指针以获得下一个块
pBlock=pEnd;
}
}
}
//关于当前系统的信息
voidShowProcessAddress()
{
intlineX=0,lineY=0;
intflag=0;
SYSTEM_INFOsys_info;//系统信息结构
ZeroMemory(&sys_info,sizeof(sys_info));//初始化
while(!
kbhit())
{
//使用winapi控制缓冲区刷新输出
if(flag==0)
{
console_getxy(lineX,lineY);
flag++;
}
else
{
console_gotoxy(lineX,lineY);
}
//获得系统信息
GetSystemInfo(&sys_info);
printf("虚拟内存分页大小:
%dKB\n",sys_info.dwPageSize/1024);
printf("处理器总数:
%d\n",sys_info.dwNumberOfProcessors);
printf("处理器架构:
%d\n",sys_info.dwProcessorType);
printf("虚拟内存粒度:
%dKB\n",sys_info.dwAllocationGranularity/1024);
printf("体系结构相关的处理器等级:
%d\n",sys_info.wProcessorLevel);
printf("体系结构相关的处理器修订:
%x\n",sys_info.wProcessorRevision);
printf("应用最小地址:
0x%0.8x\n",sys_info.lpMinimumApplicationAddress);
printf("应用最大地址:
0x%0.8x\n",sys_info.lpMaximumApplicationAddress);
printf("应用可用虚拟内存大小:
%0.2fGB\n",((DWORD)sys_info.lpMaximumApplicationAddress
-(DWORD)sys_info.lpMinimumApplicationAddress)/(1024.0*1024.0*1024.0));
Sleep(1000);
}
}
voidShowMemory()
{
intlineX=0,lineY=0;
intflag=0;
MEMORYSTATUStotal;
total.dwLength=sizeof(total);
while(!
kbhit())
{
//使用winapi控制缓冲区刷新输出
if(flag==0)
{
console_getxy(lineX,lineY);
flag++;
}
else
{
console_gotoxy(lineX,lineY);
}
//得到当前物理内存和虚拟内存
GlobalMemoryStatus(&total);
cout<<"加载的内存:
"<cout<<"总的物理内存:
"<cout<<"可用物理内存:
"<cout<<"总的虚拟内存:
"<<(total.dwTotalVirtual/DIV)<<"MB\n";
cout<<"可用虚拟内存:
"<<(total.dwAvailVirtual/DIV)<<"MB\n";
cout<<"总的页的大小:
"<cout<<"可用页大小:
"<Sleep(1000);
}
}
voidShowPerformance()
{
intlineX=0,lineY=0;
intflag=0;
PERFORMANCE_INFORMATIONperfor_info;
perfor_info.cb=sizeof(perfor_info);
while(!
kbhit())
{
//使用winapi控制缓冲区刷新输出
if(flag==0)
{
console_getxy(lineX,lineY);
flag++;
}
else
{
console_gotoxy(lineX,lineY);
}
GetPerformanceInfo(&perfor_info,sizeof(perfor_info));
cout<<"分页大小:
"<cout<<"系统提交的页面总数:
"<cout<<"系统提交的页面限制:
"<cout<<"系统提交的页面峰值:
"<cout<<"按页分配的物理内存总数:
"<cout<<"按页分配的物理内存可用量:
"<cout<<"系统物理内存占用:
"<<(perfor_info.PhysicalTotal-perfor_info.PhysicalAvailable)*(perfor_info.PageSize/1024)*1.0/DIV<<"GB"<cout<<"系统物理内存可用:
"<cout<<"系统物理内存总数:
"<cout<<"系统缓存总量:
"<cout<<"系统内核内存占据页面总数:
"<cout<<"系统内核内存占据分页页面数:
"<cout<<"系统内核内存占据不分页页面数:
"<cout<<"系统句柄总量:
"<cout<<"系统进程总量:
"<cout<<"系统线程总量:
"<Sleep(1000);
}
}
//如果pid为-1,获取所有进程
voidShowAllProcess(intpid)
{
PROCESSENTRY32pe32;//存储进程信息
pe32.dwSize=sizeof(pe32);//在使用这个结构前,先设置它的大小
PROCESS_MEMORY_COUNTERSppsmemCounter;//struct,存储进程内存的使用信息,便于用函数GetProcessMemoryInfo获取进程的相关信息
ppsmemCounter.cb=sizeof(ppsmemCounter);//初始化大小
HANDLEhProcessSnap;
hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//快照句柄
HANDLEhProcess;//进程句柄
if(hProcessSnap==INVALID_HANDLE_VALUE){
printf("创建进程快照失败.\n");
exit(0);
}
//遍历进程快照,轮流显示每个进程的信息
BOOLbMore=Process32First(hProcessSnap,&pe32);//获取系统快照第一个进程的信息,结果返回到pe32结构里
printf("进程的工作集信息:
\n");
while(bMore){
if(pid!
=-1)
{
if(pid==pe32.th32ProcessID)
{
wcout<<"进程名称:
"<cout<<"进程ID:
"<cout<<"线程数:
"<hProcess=GetProcessHandle(pe32.th32ProcessID);
GetProcessMemoryInfo(hProcess,&ppsmemCounter,sizeof(ppsmemCounter));//进程内存使用信息(存储于ppsmemCounter中)
cout<<"已提交:
"<cout<<"工作集:
"<cout<<"工作集峰值:
"<}
bMore=Process32Next(hProcessSnap,&pe32);//获取系统快照下一个进程信息
}
else
{
wcout<<"进程名称:
"<cout<<"进程ID:
"<cout<<"线程数:
"<hProcess=GetProcessHandle(pe32.th32ProcessID);
GetProcessMemoryInfo(hProcess,&ppsmemCounter,sizeof(ppsmemCounter));//进程内存使用信息(存储于ppsmemCounter中)
cout<<"已提交:
"<cout<<"工作集:
"<cout<<"工作集峰值:
"<bMore=Process32Next(hProcessSnap,&pe32);//获取系统快照下一个进程信息
}
}
CloseHandle(hProcessSnap);//关闭快照
}
voidQuerySingleProcess()
{
intlineX=0,lineY=0;
intflag=0;
HANDLEhProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//快照句柄
HANDLEhProcess;//进程句柄
if(hProcessSnap==INVALID_HANDLE_VALUE){
printf("CreateToolhelp32Snapshot调用失败.\n");
exit(0);
}
cout<<"输入进程ID,查询进程的内存分布空间:
"<intPID=0;
cin>>PID;
hProcess=GetProcessHandle(PID);
ShowAllProcess(PID);
WalkVM(hProcess)