用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;
}
相关推荐
咩咦11 分钟前
C++学习笔记23:const 成员函数
c++·学习笔记·类和对象·const·this指针·const成员函数
3DVisionary1 小时前
精密模具电极如何测形变?蓝光三维扫描3D检测方案解析
c++·数码相机·蓝光三维扫描·质量控制 qc·形位公差分析·模具电极检测·非接触三维测量
小小编程路1 小时前
C++类作用域
java·jvm·c++
计算机安禾2 小时前
【c++面向对象编程】第46篇:CRTP(奇异递归模板模式):静态多态的妙用
开发语言·c++·算法
hhcgchpspk2 小时前
easyx按键游戏
c++·stm32·单片机·游戏·easyx
郝学胜-神的一滴2 小时前
Qt 高级开发 011: 跨线程信号槽实战
开发语言·c++·qt·程序人生·开源软件·用户界面
学困昇2 小时前
Linux 动静态库制作与原理:从 .a、.so 到 ELF 加载一次讲透
linux·运维·服务器·c语言·开发语言·c++·人工智能
basketball6162 小时前
C++面试考点 头文件与实现文件形式
开发语言·c++
历程里程碑2 小时前
56 . 高效ET非阻塞IO服务器设计指南
java·运维·服务器·开发语言·数据结构·c++·排序算法
计算机安禾3 小时前
【c++面向对象编程】第44篇:typename与class的区别,依赖类型名与template消除歧义
java·jvm·c++