C++ 簡單的CPU使用率監控程序

 主要代碼如下:

// 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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章