主要代码如下:
// test4.cpp : 定义控制台应用程序的入口点。
// 简单的监控指定程序列表的CPU使用率
#include "stdafx.h"
#include<thread>
#include <windows.h>
#include <stdint.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <Psapi.h>
#include <string>
#include <map>
using namespace std;
typedef struct EnumHWndsArg
{
std::vector<HWND> *vecHWnds;
DWORD dwProcessId;
}EnumHWndsArg, *LPEnumHWndsArg;
HANDLE GetProcessHandleByID(int nID)//通过进程ID获取进程句柄
{
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, nID);
}
std::vector<DWORD> GetProcessIDByName(const char* pName)
{
std::vector<DWORD> vPID;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) {
return vPID;
}
PROCESSENTRY32 pe = { sizeof(pe) };
for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
if (strcmp(pe.szExeFile, pName) == 0) {
vPID.push_back(pe.th32ProcessID);
}
}
CloseHandle(hSnapshot);
return vPID;
}
BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam)
{
EnumHWndsArg *pArg = (LPEnumHWndsArg)lParam;
DWORD processId;
GetWindowThreadProcessId(hwnd, &processId);
if (processId == pArg->dwProcessId)
{
pArg->vecHWnds->push_back(hwnd);
//printf("%p\n", hwnd);
}
return TRUE;
}
void GetHWndsByProcessID(DWORD processID, std::vector<HWND> &vecHWnds)
{
EnumHWndsArg wi;
wi.dwProcessId = processID;
wi.vecHWnds = &vecHWnds;
EnumWindows(lpEnumFunc, (LPARAM)&wi);
}
LONGLONG FileTime2UInt64(const _In_ FILETIME& ftTime)
{
LARGE_INTEGER l_intger;
l_intger.LowPart = ftTime.dwLowDateTime;
l_intger.HighPart = ftTime.dwHighDateTime;
return l_intger.QuadPart;
}
std::map<LONGLONG, LONGLONG> gmapLastSysTime;
std::map<LONGLONG, LONGLONG> gmapLastNowTime;
void ThreadTest()
{
FILE* fpIn;
fopen_s(&fpIn, "load.config", "r+");
if (!fpIn)
return;
std::vector<std::string> vNameList;
char aBuff[128];
while (!feof(fpIn))
{
fgets(aBuff, sizeof(aBuff), fpIn);
if (strlen(aBuff) > 1)
{
if(aBuff[strlen(aBuff) - 1] == '\n')
aBuff[strlen(aBuff) - 1] = '\0';
vNameList.push_back(aBuff);
}
}
fclose(fpIn);
char aName[128];
while (1)
{
for (auto itName : vNameList)
{
sprintf_s(aName, sizeof(aName), "%s.exe", itName.c_str());
std::vector<DWORD> vPID = GetProcessIDByName(aName);
for (auto it : vPID)
{
std::string strOut;
char strInfo[1024];
DWORD pid = it;
sprintf_s(strInfo, "\npid:%d\n", pid);
strOut.append(strInfo);
HANDLE handle = GetProcessHandleByID(static_cast<int>(pid));
PROCESS_MEMORY_COUNTERS_EX pmc = { 0 };
int a = sizeof(pmc);
if (!GetProcessMemoryInfo(handle, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)))
{
DWORD errCode = GetLastError();
printf_s("GetProcessMemoryInfo fail, lastErrorCode:%d\n", errCode);
return;
}
//占用的物理内存峰值
sprintf_s(strInfo, "PeakWorkingSetSize:%d(KB)\n", pmc.PeakWorkingSetSize / 1024);
strOut.append(strInfo);
//当前占用的物理内存
sprintf_s(strInfo, "WorkingSetSize:%d(KB)\n", pmc.WorkingSetSize / 1024);
strOut.append(strInfo);
//占用的虚拟内存峰值(物理内存+页文件),对应任务管理器中的commit列值
sprintf_s(strInfo, "PeakPagefileUsage:%d(KB)\n", pmc.PeakPagefileUsage / 1024);
strOut.append(strInfo);
//当前占用的虚拟内存(物理内存+页文件),对应任务管理器中的commit列值
sprintf_s(strInfo, "PagefileUsage:%d(KB)\n", pmc.PagefileUsage / 1024);
strOut.append(strInfo);
//等同于当前占用的虚拟内存(物理内存+页文件),对应任务管理器中的commit列值,并不是任务管理器中的私有独占内存的意思。
sprintf_s(strInfo, "PrivateUsage:%d(KB)\n", pmc.PrivateUsage / 1024);
strOut.append(strInfo);
//printf("%s", strOut.c_str());
FILETIME ftNow, ftCreate, ftExit, ftKernel, ftUser;
SYSTEM_INFO info;
GetSystemInfo(&info);
GetSystemTimeAsFileTime(&ftNow);
if (!GetProcessTimes(handle, &ftCreate, &ftExit, &ftKernel, &ftUser))
return;
LONGLONG llSys = (FileTime2UInt64(ftKernel) + FileTime2UInt64(ftUser)) / info.dwNumberOfProcessors;
LONGLONG llNow = FileTime2UInt64(ftNow);
if (gmapLastSysTime[pid] && gmapLastNowTime[pid])
{
LONGLONG llSysDelta = llSys - gmapLastSysTime[pid];
LONGLONG llTimeDelta = llNow - gmapLastNowTime[pid];
float fCpu = 100.0*(float)llSysDelta / (float)llTimeDelta;
SYSTEMTIME tm;
GetLocalTime(&tm);
char aData[1024];
sprintf_s(aData, sizeof(aData), "%u-%u-%u_%u:%u:%u cpu:%.2f - time:%lld\n", tm.wYear,tm.wMonth,tm.wDay,tm.wHour,tm.wMinute,tm.wSecond, fCpu, llTimeDelta);
FILE* fpOut;
char aFileName[256];
sprintf_s(aFileName, sizeof(aFileName), "cpu\\%s_%d.log", aName, pid);
fopen_s(&fpOut, aFileName, "a+");
if(fpOut)
{
fputs(aData, fpOut);
fflush(fpOut);
fclose(fpOut);
}
else
{
printf_s("open[%s]failed\n", aFileName);
}
}
gmapLastSysTime[pid] = llSys;
gmapLastNowTime[pid] = llNow;
}
}
Sleep(1000);
//printf_s("\n\n====================\n");
}
}
int main()
{
std::thread mythread(ThreadTest);
mythread.join();
return 0;
}
配置文件 load.config:根据实际需要进行配置,比如WeChat.exe GameServer.exe WebServer.exe
WeChat
GameServer
WebServer
输出到 cpu\xxxxx.log,形式如下
2020-5-25_18:0:14 cpu:0.00 - time:10781641
2020-5-25_18:0:15 cpu:0.00 - time:10468579
2020-5-25_18:0:16 cpu:0.72 - time:10781368
2020-5-25_18:0:17 cpu:0.00 - time:10469099
2020-5-25_18:0:18 cpu:0.00 - time:10781901