用PDH库获取CPU使用率(源码)

1、概述

PDH工作原理:

第一次采集:获取当前CPU的"累计运行时间"

第二次采集:一段时间后,再次获取累计运行时间

计算差值:

用第二次的值,减去第一次的值,得出这段时间内的活跃时间占比。

所以会有如下结论:

调用间隔 返回值含义 是否「实时」
1 秒 过去 1 秒的 CPU 使用率 ✅ 实时
5 秒 过去 5 秒的平均使用率 ✅ 基本实时
30 秒 过去 30 秒的平均使用率 ⚠️ 略有延迟
30 分钟 过去 30 分钟的平均使用率 ❌ 不实时,是历史平均

2、源码

2.1、调用示例

cpp 复制代码
    CCpuUsageUtil cpu;
    if (!cpu.Init())
    {
        printf("初始化失败!可能是计数器名称错误(中文系统?)\n");
        return -1;
    }
    cpu.GetUsage();
    Sleep(2000);
    int usage = cpu.GetUsage();
    printf("CPU 使用率: %d%%\n", usage);

2.2、源码

cpp 复制代码
#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
cpp 复制代码
#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;
}
相关推荐
liu****19 小时前
2.深入浅出理解虚拟化与容器化(含Docker实操全解析)
运维·c++·docker·容器·虚拟化技术
A9better20 小时前
C++——不一样的I/O工具与名称空间
开发语言·c++·学习
王老师青少年编程20 小时前
2024年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第2题)
c++·题解·真题·初赛·信奥赛·csp-s·提高组
MSTcheng.20 小时前
【C++】C++11新特性(三)
开发语言·c++·c++11
田野追逐星光20 小时前
STL容器list的模拟实现
开发语言·c++·list
StandbyTime20 小时前
《算法笔记》学习记录-第二章 C/C++快速入门
c++·算法笔记
我在人间贩卖青春21 小时前
C++之结构体与类
c++··结构体
rainbow688921 小时前
C++实现JSON Web计算器
c++
C++ 老炮儿的技术栈21 小时前
Qt Creator中不写代如何设置 QLabel的颜色
c语言·开发语言·c++·qt·算法
知无不研21 小时前
lambda表达式的原理和由来
java·开发语言·c++·lambda表达式