Copyright © 2024 Squareroot_2, All rights reserved.
实验三 遍历进程地址空间
一、实验目的
通过设计程序实时显示某个进程的虚拟地址空间布局和工作集信息,加深对内存管理的理解。
二、实验内容
在Windows系统下设计程序,实时显示某个进程的虚拟地址空间布局和工作集信息。
三、程序设计与实现
实验环境:windows 10
开发环境:Visual Studio 2022
程序源码:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <iomanip>
#pragma comment(lib,"Shlwapi.lib")
using namespace std;
void showMask(DWORD dwTarget, DWORD dwMask, string type) {
if ((dwTarget & dwMask) == dwMask) {
cout << ", " << type;
}
}
void showProtection(DWORD dwTarget) {
showMask(dwTarget, PAGE_READONLY, "PAGE_READONLY");
showMask(dwTarget, PAGE_GUARD, "PAGE_GUARD");
showMask(dwTarget, PAGE_NOCACHE, "PAGE_NOCACHE");
showMask(dwTarget, PAGE_READWRITE, "PAGE_READWRITE");
showMask(dwTarget, PAGE_WRITECOPY, "PAGE_WRITECOPY");
showMask(dwTarget, PAGE_EXECUTE, "PAGE_EXECUTE");
showMask(dwTarget, PAGE_EXECUTE_READ, "PAGE_EXECUTE_READ");
showMask(dwTarget, PAGE_EXECUTE_READWRITE, "PAGE_EXECUTE_READWRITE");
showMask(dwTarget, PAGE_EXECUTE_WRITECOPY, "PAGE_EXECUTE_WRITECOPY");
showMask(dwTarget, PAGE_NOACCESS, "PAGE_NOACCESS");
}
//遍历整个虚拟内存,并显示各内存区属性的工作程序
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) {
SIZE_T t = VirtualQueryEx(hProcess, pBlock, &mbi, sizeof(mbi));
if (t == sizeof(mbi)) {
//计算块的结尾及其长度
LPCVOID pEnd = (PBYTE)pBlock + mbi.RegionSize;
TCHAR szSize[MAX_PATH];
//将数字转换成字符串
StrFormatByteSize(mbi.RegionSize, szSize, MAX_PATH);
//显示块地址和长度
cout.fill('0');
cout << hex << setw(8) << (DWORD)pBlock
<< "-"
<< hex << setw(8) << (DWORD)pEnd
<< (strlen(szSize) == 7 ? "(" : ",(") << szSize << ")";
//<< "(" << szSize << ")";
//显示块的状态
string state = " state: ";
switch (mbi.State)
{
case MEM_COMMIT:
state += "已提交";
break;
case MEM_FREE:
state += "空闲 ";
break;
case MEM_RESERVE:
state += "已预留";
break;
}
cout << state;
//显示保护
if (mbi.Protect == 0 && mbi.State != MEM_FREE) {
mbi.Protect = PAGE_READONLY;
}
showProtection(mbi.Protect);
//显示类型
string type = ", type: ";
switch (mbi.Type)
{
case MEM_IMAGE:
type += "Image";
break;
case MEM_MAPPED:
type += "Mapped";
break;
case MEM_PRIVATE:
type += "Private";
break;
}
pBlock = pEnd;
cout << endl;
}
}
}
int main(int argc, char* argv[]) {
//获得每个进程的信息
cout << "各个进程的信息: " << endl;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
BOOL bMore = ::Process32First(hProcessSnap, &pe);
while (bMore)
{
HANDLE hP = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
PROCESS_MEMORY_COUNTERS pmc;
ZeroMemory(&pmc, sizeof(pmc));
if (GetProcessMemoryInfo(hP, &pmc, sizeof(pmc)) == TRUE)
{
cout << "进程ID: ";
wcout << pe.th32ProcessID;
cout << "\t虚拟内存的大小为: " << (float)pmc.WorkingSetSize / 1024 << "KB";
cout << "\t进程名称: ";
wcout << pe.szExeFile << endl;
}
bMore = ::Process32Next(hProcessSnap, &pe);
}
cout << endl;
//显示进程的虚拟地址空间布局和工作集信息
int process_id;
do {
cout << "显示进程的虚拟地址空间布局和工作集信息" << endl
<< "输入要查询的进程ID(退出请输入-1): ";
cin >> process_id;
if (process_id >= 0) {
HANDLE hP = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);
walkVM(hP);
}
} while (process_id != -1);
return 0;
}
四、实验结果及分析
五、实验收获与体会
通过本实验,熟练掌握了GetSystemInfo, VirtualQueryEx,VirtualAlloc, GetPerformanceInfo, GlobalMemoryStatusEx等Windows下关于内存信息的系统调用函数,了解了系统内部内存的工作方式和工作情况,对Windows操作系统的内存分配方式有了更加深入的了解。