用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;
}
相关推荐
散峰而望1 小时前
C++数组(二)(算法竞赛)
开发语言·c++·算法·github
利刃大大2 小时前
【动态规划:背包问题】完全平方数
c++·算法·动态规划·背包问题·完全背包
笑非不退3 小时前
C# c++ 实现程序开机自启动
开发语言·c++·c#
AA陈超4 小时前
从0开始学习 **Lyra Starter Game** 项目
c++·笔记·学习·游戏·ue5·lyra
q***T5834 小时前
C++在游戏中的Unreal Engine
c++·游戏·虚幻
保持低旋律节奏4 小时前
C++——C++11特性
开发语言·c++·windows
小张成长计划..5 小时前
【C++】16:模板进阶
c++·算法
CoderIsArt6 小时前
SAM-5 核心类体系的 C++ 完整设计
c++·sam5
CS_浮鱼6 小时前
【Linux进阶】mmap实战:文件映射、进程通信与LRU缓存
linux·运维·c++·缓存
YJlio6 小时前
「C++ 40 周年」:从“野蛮生长的指针地狱”到 AI 时代的系统底座
c++·人工智能·oracle