用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;
}
相关推荐
让我们一起加油好吗4 小时前
【基础算法】多源 BFS
c++·算法·bfs·宽度优先·多源bfs
冷崖4 小时前
定时器的学习(二)
linux·c++·学习
大胆飞猪4 小时前
高并发内存池日志
c++·项目
想唱rap4 小时前
C++ string类的使用
开发语言·c++·笔记·算法·新浪微博
胖咕噜的稞达鸭4 小时前
C++中的父继子承(2)多继承菱形继承问题,多继承指针偏移,继承组合分析+高质量习题扫尾继承多态
c语言·开发语言·数据结构·c++·算法·链表·c#
小苏兮5 小时前
【C++】priority_queue和deque的使用与实现
开发语言·c++·学习
Mr_WangAndy5 小时前
C++设计模式_行为型模式_迭代器模式Iterator
c++·设计模式·迭代器模式
FL16238631295 小时前
C++基于opencv实现的暗通道的先验图像去雾
c++·opencv·计算机视觉
仰泳的熊猫6 小时前
LeetCode:538. 把二叉搜索树转换为累加树/1038. 从二叉搜索树到更大和树
数据结构·c++·算法·leetcode