#include<iostream> #include<cstdio> #include<windows.h> #include<tchar.h> #include<psapi.h> #include<Tlhelp32.h> #include<shlwapi.h> #include<iomanip> #include"conio.h" #include<string.h> #pragma comment(lib, "psapi.lib") #pragma comment(lib, "Shlwapi.lib") #pragma warning(disable: 4996) using namespace std; #define breadth 10 #define wire (1024*1024)
//WIN API得到当前console 的(x,y) void console_gotoxy(int x, int y) { // 得到当前console的句柄 HANDLE hc = GetStdHandle(STD_OUTPUT_HANDLE); COORD cursor = { x, y }; //设置新的cursor位置 SetConsoleCursorPosition(hc, cursor); }
//WIN API设置当前console 的(x, y) void console_getxy(int& x, int& y) { // 得到当前console的句柄 HANDLE hc = GetStdHandle(STD_OUTPUT_HANDLE); // 屏幕缓冲区信息 CONSOLE_SCREEN_BUFFER_INFO csbi; //得到相应缓冲区信息 GetConsoleScreenBufferInfo(hc, &csbi); x = csbi.dwCursorPosition.X; y = csbi.dwCursorPosition.Y; }
//用来打开一个已存在的进程对象,并返回进程的句柄。 HANDLE GetProcessHandle(int ProcessID) { return OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);//进程访问权限 进程句柄是否可被继承 进程PID }
//显示保护标记,该标记表示允许应用程序对内存进行访问的类型 inline bool TestSet(DWORD dwTarget, DWORD dwMask) { return ((dwTarget &dwMask) == dwMask); } #define SHOWMASK(dwTarget, type) \ if (TestSet(dwTarget, PAGE_##type)) \ {cout<<", "<<# type;}
void ShowProtection(DWORD dwTarget) { //定义的页面保护方式 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); }
//遍历整个虚拟内存,并显示各内存区属性的工作程序 (P292) 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) { //获得下一个虚拟内存块的信息 if (VirtualQueryEx(hProcess, //相关的进程 pBlock, //开始位置 &mbi, //缓冲区 sizeof(mbi)) == sizeof(mbi)) //长度的确认,如果失败则返回0 { //块的结尾指针 //计算块的结尾及其长度 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 << "(" << szSize << ")";
//显示块的状态 switch (mbi.State) { case MEM_COMMIT: printf(" Committed"); break; //已分配 case MEM_FREE: printf(" Free"); break; //自由 case MEM_RESERVE: printf(" Reserved"); break; //保留 }
//显示保护 if (mbi.Protect == 0 && mbi.State != MEM_FREE) { mbi.Protect = PAGE_READONLY; } ShowProtection(mbi.Protect);
//显示类型 switch (mbi.Type) { case MEM_IMAGE: printf(", Image "); break; //可执行映像 case MEM_MAPPED: printf(", Mapped"); break; //内存映射文件 case MEM_PRIVATE: printf(", Private"); break; //私有内存区 }
//检测可执行的映像 TCHAR szFilename[MAX_PATH]; if (GetModuleFileName( (HMODULE)pBlock, //实际虚拟内存的模块句柄 szFilename, //完全指定的文件名称 MAX_PATH) > 0) //实际使用的缓冲区长度 { //除去路径并显示 PathStripPath(szFilename); printf(",Module:"); int i = 0; while (szFilename[i] != '\0') printf("%c", szFilename[i++]);
} printf("\n"); //移动块指针以获得下一个块 pBlock = pEnd;
} } }
//实时显示进程相关信息 void ShowProcessAddress() { int lineX = 0, lineY = 0; int flag = 0; SYSTEM_INFO sys_info; //系统信息结构 ZeroMemory(&sys_info, sizeof(sys_info));// 初始化 while (!kbhit()) { //使用win api控制缓冲区刷新输出 if (flag == 0) { console_getxy(lineX, lineY); flag++; } else { console_gotoxy(lineX, lineY); } //获得系统信息 //SYSTEM_INFO结构包含有关当前计算机系统的信息。包括处理器类型,页面大小,内存地址,和OEM标识符。 GetSystemInfo(&sys_info); printf("虚拟内存分页大小: %d KB\n", sys_info.dwPageSize / 1024); printf("处理器总数: %d\n", sys_info.dwNumberOfProcessors); printf("处理器架构: %d\n", sys_info.dwProcessorType); printf("虚拟内存粒度: %d KB\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.2f GB\n", ((DWORD)sys_info.lpMaximumApplicationAddress - (DWORD)sys_info.lpMinimumApplicationAddress) / (1024.0*1024.0*1024.0)); Sleep(1000); }
}
//实时显示系统内存相关信息 void ShowMemory() { int lineX = 0, lineY = 0; int flag = 0; MEMORYSTATUS total; total.dwLength = sizeof(total); PERFORMANCE_INFORMATION perfor_info; perfor_info.cb = sizeof(perfor_info); while (!kbhit()) { //使用win api控制缓冲区刷新输出 if (flag == 0) { console_getxy(lineX, lineY); flag++; } else { console_gotoxy(lineX, lineY); } //得到当前物理内存和虚拟内存 //内存信息 GlobalMemoryStatus(&total); //指向保存性能数据的PERFORMANCE_INFORMATION结构的指针。PERFORMANCE_INFORMATION结构的大小,字节为单位。 GetPerformanceInfo(&perfor_info, sizeof(perfor_info)); cout << "加载的内存: " << total.dwMemoryLoad << "%\n"; cout << "总的物理内存: " << total.dwTotalPhys / wire << "MB\n"; cout << "可用物理内存: " << total.dwAvailPhys / wire << "MB\n"; cout << "总的虚拟内存: " << (total.dwTotalVirtual / wire) << "MB\n"; cout << "可用虚拟内存: " << (total.dwAvailVirtual / wire) << "MB\n"; cout << "总的页的大小: " << total.dwTotalPageFile / wire << "MB\n"; cout << "可用页大小: " << total.dwAvailPageFile / wire << "MB\n"; cout << "分页大小: " << perfor_info.PageSize / 1024 << "KB" << endl; cout << "系统提交的页面总数: " << perfor_info.CommitTotal << " Pages" << endl; cout << "系统物理内存占用: " << (perfor_info.PhysicalTotal - perfor_info.PhysicalAvailable)*(perfor_info.PageSize / 1024)*1.0 / wire << "GB" << endl;
cout << "系统物理内存可用: " << perfor_info.PhysicalAvailable*(perfor_info.PageSize / 1024)*1.0 / wire << "GB" << endl;
cout << "系统物理内存总数: " << perfor_info.PhysicalTotal*(perfor_info.PageSize / 1024)*1.0 / wire << "GB" << endl; cout << "系统缓存总量: " << perfor_info.PhysicalAvailable << " Pages" << endl; Sleep(1000); } }
//如果pid 为-1,获取所有进程 //查询所有进程控制信息 void ShowAllProcess(int pid) { PROCESSENTRY32 pe32; //存储进程信息 pe32.dwSize = sizeof(pe32); //在使用这个结构前,先设置它的大小 PROCESS_MEMORY_COUNTERS ppsmemCounter;//struct,存储进程内存的使用信息,便于用函数GetProcessMemoryInfo获取进程的相关信息 ppsmemCounter.cb = sizeof(ppsmemCounter); //初始化大小 HANDLE hProcessSnap;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //快照句柄 HANDLE hProcess;//进程句柄 if (hProcessSnap == INVALID_HANDLE_VALUE) { printf("创建进程快照失败.\n"); exit(0); } //遍历进程快照,轮流显示每个进程的信息
BOOL bMore = Process32First(hProcessSnap, &pe32); //获取系统快照第一个进程的信息,结果返回到pe32结构里 printf("进程的工作集信息:\n"); while (bMore) { if (pid != -1) { if (pid == pe32.th32ProcessID) { wcout << "进程名称:" << pe32.szExeFile << endl;//进程信息(存储于pe32中) cout << "进程ID:" << pe32.th32ProcessID << endl; cout << "线程数:" << pe32.cntThreads << endl; hProcess = GetProcessHandle(pe32.th32ProcessID); GetProcessMemoryInfo(hProcess, &ppsmemCounter, sizeof(ppsmemCounter));//进程内存使用信息(存储于ppsmemCounter中) cout << "已提交:" << ppsmemCounter.PagefileUsage / 1024 << " KB" << endl; cout << "工作集:" << ppsmemCounter.WorkingSetSize / 1024 << " KB" << endl; cout << "工作集峰值:" << ppsmemCounter.PeakWorkingSetSize / 1024 << " KB" << endl; }
bMore = Process32Next(hProcessSnap, &pe32);//获取系统快照下一个进程信息 } else//pid=0时,显示单个信息 {
wcout << "进程名称:" << pe32.szExeFile << endl;//进程信息 cout << "进程ID:" << pe32.th32ProcessID << endl; cout << "线程数:" << pe32.cntThreads << endl; hProcess = GetProcessHandle(pe32.th32ProcessID);
GetProcessMemoryInfo(hProcess, &ppsmemCounter, sizeof(ppsmemCounter));//进程内存使用信息(存储于ppsmemCounter中) cout << "已提交:" << ppsmemCounter.PagefileUsage / 1024 << " KB" << endl; cout << "工作集:" << ppsmemCounter.WorkingSetSize / 1024 << " KB" << endl; cout << "工作集峰值:" << ppsmemCounter.PeakWorkingSetSize / 1024 << " KB" << endl; bMore = Process32Next(hProcessSnap, &pe32);//获取系统快照下一个进程信息 } }
CloseHandle(hProcessSnap); //关闭快照 }
//查询单个进程控制信息 void QuerySingleProcess() { int lineX = 0, lineY = 0; int flag = 0; HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //快照句柄 HANDLE hProcess;//进程句柄 if (hProcessSnap == INVALID_HANDLE_VALUE) { printf("CreateToolhelp32Snapshot 调用失败.\n"); exit(0); } cout << "输入进程ID,查询进程的内存分布空间:" << endl; int PID = 0; cin >> PID; hProcess = GetProcessHandle(PID); ShowAllProcess(PID); WalkVM(hProcess); Sleep(1000);
CloseHandle(hProcess);//关闭进程 } int main() { cout << "Memory Monitor" << endl; while (1) { int mode = 0; cout << "1.实时显示进程相关信息" << endl; cout << "2.实时显示系统内存相关信息" << endl; cout << "3.查询所有进程控制信息" << endl; cout << "4.查询单个进程控制信息" << endl; cin >> mode; switch (mode) { case 1: ShowProcessAddress(); break; case 2: ShowMemory(); break; case 3: ShowAllProcess(-1); break; case 4: QuerySingleProcess(); break;
default:cout << "输入格式不正确,请重新输出数字" << endl; } } return 0;
}