用PDH库获取CPU使用率(源码)
1、概述
PDH工作原理:
第一次采集:获取当前CPU的"累计运行时间"
第二次采集:一段时间后,再次获取累计运行时间
计算差值:
用第二次的值,减去第一次的值,得出这段时间内的活跃时间占比。
所以会有如下结论:
调用间隔 | 返回值含义 | 是否「实时」 |
---|---|---|
1 秒 | 过去 1 秒的 CPU 使用率 | ✅ 实时 |
5 秒 | 过去 5 秒的平均使用率 | ✅ 基本实时 |
30 秒 | 过去 30 秒的平均使用率 | ⚠️ 略有延迟 |
30 分钟 | 过去 30 分钟的平均使用率 | ❌ 不实时,是历史平均 |
2、源码
2.1、调用示例
CCpuUsageUtil cpu;if (!cpu.Init()){printf("初始化失败!可能是计数器名称错误(中文系统?)\n");return -1;}cpu.GetUsage();Sleep(2000);int usage = cpu.GetUsage();printf("CPU 使用率: %d%%\n", usage);
2.2、源码
#ifndef Cpu_Usage_h_
#define Cpu_Usage_h_#include <pdh.h>
#include <pdhmsg.h>#define MAX_RAW_VALUES 20// \Processor(_Total):表示所有CPU核心的总和
// % Processor Time:表示CPU使用率(百分比)
const wchar_t g_szCounterName[] = L"\\Processor Information(_Total)\\% Processor Time";typedef struct _tag_PDHCounterStruct {HCOUNTER hCounter; // Handle to the counter - given to use by PDH Library//int nNextIndex; // element to get the next raw value//int nOldestIndex; // element containing the oldes raw value//int nRawCount; // number of elements containing raw values//PDH_RAW_COUNTER a_RawValue[MAX_RAW_VALUES]; // Ring buffer to contain raw values
} PDHCOUNTERSTRUCT, *PPDHCOUNTERSTRUCT;class CCpuUsageUtil
{
public:CCpuUsageUtil();virtual ~CCpuUsageUtil();BOOL Init();void Unit();int GetUsage();protected:PPDHCOUNTERSTRUCT m_pCounterStruct;HQUERY m_hQuery;
};#endif
#include "CpuUsage.h"#pragma comment(lib,"PDH.lib")CCpuUsageUtil::CCpuUsageUtil()
{m_hQuery = NULL;m_pCounterStruct = NULL;
}CCpuUsageUtil::~CCpuUsageUtil()
{Unit();
}BOOL CCpuUsageUtil::Init()
{if (ERROR_SUCCESS != PdhOpenQuery(NULL, 0, &m_hQuery)){return FALSE;}m_pCounterStruct = new PDHCOUNTERSTRUCT;PDH_STATUS pdh_status = PdhAddCounter(m_hQuery, g_szCounterName, (DWORD)m_pCounterStruct, &(m_pCounterStruct->hCounter));if (ERROR_SUCCESS != pdh_status){Unit();return FALSE;}PdhCollectQueryData(m_hQuery);return TRUE;
}void CCpuUsageUtil::Unit()
{PdhCloseQuery(m_hQuery);m_hQuery = nullptr;if (m_pCounterStruct){delete m_pCounterStruct;m_pCounterStruct = nullptr;}
}int CCpuUsageUtil::GetUsage()
{PDH_FMT_COUNTERVALUE pdhFormattedValue;PdhCollectQueryData(m_hQuery);if (ERROR_SUCCESS != PdhGetFormattedCounterValue(m_pCounterStruct->hCounter, PDH_FMT_LONG, NULL, &pdhFormattedValue)){return 0;}return pdhFormattedValue.longValue;
}