跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

Windows 平台 C++ 基于 PDH API 实现 CPU 使用率监控

介绍在 Windows 平台下使用 C++ 语言结合原生 PDH API 实现 CPU 使用率的实时监控功能。通过 PdhOpenQuery 初始化查询句柄,添加 Processor Information 计数器,经过预热采样获取浮点型使用率数据。代码包含完整的错误处理、异常值过滤及资源释放逻辑,适配 Win10/11 系统,数值与任务管理器一致,无需第三方库,轻量高效。

随缘发布于 2026/3/23更新于 2026/5/297.6K 浏览

在 Windows 平台开发性能监控类程序时,CPU 使用率是核心监控指标之一。本文基于 Windows 原生 PDH(Performance Data Helper)API,实现高精度、高兼容性的 CPU 使用率实时采集功能,代码可直接复用,适配 Win10/Win11 系统,与任务管理器 CPU 数值高度一致。

一、核心优势

  1. 原生 API:基于 Windows PDH 接口,无需第三方库,轻量化且稳定;
  2. 高精度:返回浮点型 CPU 使用率,支持自定义小数位数;
  3. 高兼容:适配 Win10/11,计数器路径经过实测验证,无数值偏差;
  4. 鲁棒性:包含完整的错误处理和异常值过滤,避免程序崩溃;
  5. 易复用:模块化设计,初始化、采集、释放功能分离,可直接集成到项目。

二、完整代码实现

#include <windows.h>
#include <pdh.h>
#include <iostream>
#include <cmath> // 用于 round() 四舍五入函数
// 链接 PDH 库,必须添加
#pragma comment(lib, "pdh.lib")
// 关闭安全警告
#pragma warning(disable:4996)
// CPU 监控句柄(全局/类成员均可,保证生命周期)
static PDH_HQUERY cpuQuery;
static PDH_HCOUNTER cpuTotal;
/**
 * @brief 初始化 CPU 使用率采集模块
 * @return bool 初始化成功返回 true,失败返回 false
 * @note 必须先调用此函数,否则 getCPUUsage 返回 0
 */
bool initCPUMonitor() {
    // 打开 PDH 查询句柄
    if (PdhOpenQuery(NULL, NULL, &cpuQuery) != ERROR_SUCCESS) {
        std::cerr << "CPU 监控初始化失败:打开查询句柄失败" << std::endl;
        return false;
    }
    // 添加 CPU 使用率计数器(Win10/11 最优路径,与任务管理器数值一致)
    if (PdhAddEnglishCounter(cpuQuery, L"\\Processor Information(_Total)\\% Processor Utility", NULL, &cpuTotal) != ERROR_SUCCESS) {
        std::cerr << "CPU 监控初始化失败:添加计数器失败" << std::endl;
        PdhCloseQuery(cpuQuery);
        return false;
    }
    // PDH 特性:首次采样必为 0,需预热采样
    PdhCollectQueryData(cpuQuery);
    Sleep(600); // 采样间隔,保证数据有效
    PdhCollectQueryData(cpuQuery);
    return true;
}
/**
 * @brief 获取实时 CPU 总使用率(%)
 * @return double CPU 使用率(0.0 ~ 100.0),保留 1 位小数,出错返回 0.0
 */
double getCPUUsage() {
    PDH_FMT_COUNTERVALUE counterVal;
    // 采集最新数据
    if (PdhCollectQueryData(cpuQuery) != ERROR_SUCCESS) {
        return 0.0;
    }
    // 格式化获取数值(双精度浮点数)
    DWORD ret = PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
    if (ret != ERROR_SUCCESS) {
        return 0.0;
    }
    // 过滤异常值 + 保留 1 位小数
    double cpuUsage = counterVal.doubleValue;
    cpuUsage = (cpuUsage >= 0.0 && cpuUsage <= 100.0) ? cpuUsage : 0.0;
    if (cpuUsage > 100.0) cpuUsage = 100.0;
    cpuUsage = round(cpuUsage * 10) / 10.0; // 四舍五入保留 1 位小数
    return cpuUsage;
}
/**
 * @brief 释放 CPU 监控资源(程序结束时调用)
 */
void releaseCPUMonitor() {
    if (cpuQuery != NULL) {
        PdhCloseQuery(cpuQuery);
        cpuQuery = NULL;
    }
}
int main() {
    // 1. 初始化 CPU 监控
    if (!initCPUMonitor()) {
        return -1;
    }
    // 2. 循环获取 CPU 使用率(每秒 1 次)
    std::cout << "CPU 使用率监控中,按 Ctrl+C 退出..." << std::endl;
    while (true) {
        double cpu = getCPUUsage();
        std::cout << "当前 CPU 使用率:" << cpu << "%" << std::endl;
        Sleep(1000);
    }
    // 3. 释放资源(实际中需在退出循环后调用)
    releaseCPUMonitor();
    return 0;
}

三、关键知识点解析

1. PDH API 核心流程
  • PdhOpenQuery:创建 PDH 查询句柄,是所有 PDH 操作的基础;
  • PdhAddEnglishCounter:添加 CPU 使用率计数器,使用英文计数器路径避免中文系统兼容问题;
  • PdhCollectQueryData:采集计数器数据,PDH 要求至少两次采样才能得到有效数值;
  • PdhGetFormattedCounterValue:将采集到的原始数据格式化为浮点数,方便使用;
  • PdhCloseQuery:释放查询句柄,避免资源泄漏。
2. 核心细节说明
(1)计数器路径选择
L"\\Processor Information(_Total)\\% Processor Utility"

这是 Win10/11 下最优的 CPU 总使用率计数器路径,相比旧版 \\Processor(_Total)\\% Processor Time,数值更贴合任务管理器,无延迟和偏差。

(2)首次采样预热

PDH API 的特性是首次采集数据必为 0,因此初始化时需要先执行两次 PdhCollectQueryData,并间隔 600ms,保证后续采集的数值有效。

(3)小数位数控制
cpuUsage = round(cpuUsage * 10) / 10.0;

通过 round() 函数实现四舍五入保留 1 位小数:

  • 放大 10 倍:将小数点后第一位变为整数位(如 25.67→256.7);
  • 四舍五入:round(256.7)→257;
  • 缩小 10 倍:257/10→25.7,最终得到 1 位小数的结果。

四、编译与运行说明

1. 编译环境
  • 编译器:MSVC(Visual Studio 2019/2022)、MinGW(需确保链接 pdh.lib);
  • 平台:Windows 10/11(32/64 位均可);
  • 字符集:默认多字节字符集即可。
2. 运行效果
CPU 使用率监控中,按 Ctrl+C 退出...
当前 CPU 使用率:5.2%
当前 CPU 使用率:4.8%
当前 CPU 使用率:6.1%
...

五、注意事项

  1. 头文件依赖:使用 round() 函数必须包含 <cmath> 头文件,否则编译报错;
  2. 资源释放:程序退出前务必调用 releaseCPUMonitor() 释放 PDH 句柄,避免内存泄漏;
  3. 采样频率:建议采样间隔≥500ms,过于频繁采样会导致数值波动,且无实际意义;
  4. 权限问题:普通用户权限即可运行,无需管理员权限;
  5. 异常值过滤:代码中已过滤 0~100 之外的异常值,避免出现负数或超过 100% 的无效数值。

总结

本文基于 Windows PDH API 实现了轻量、高效的 CPU 使用率监控功能,代码模块化程度高,可直接复用。核心要点包括:PDH 初始化预热、正确选择计数器路径、数值格式化与异常过滤。该方案相比第三方库更轻量化,相比 WMI 查询更高效,是 Windows 平台 CPU 监控的优选方案。

目录

  1. 一、核心优势
  2. 二、完整代码实现
  3. 三、关键知识点解析
  4. 1\. PDH API 核心流程
  5. 2\. 核心细节说明
  6. (1)计数器路径选择
  7. (2)首次采样预热
  8. (3)小数位数控制
  9. 四、编译与运行说明
  10. 1\. 编译环境
  11. 2\. 运行效果
  12. 五、注意事项
  13. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于 SSM 和 Vue 的在线投稿系统设计与实现
  • 2026 年 2 月 AIGC 行业模型发布及前沿资讯
  • Python FastAPI 入门实战:从环境搭建到接口开发
  • 基于 Apache IoTDB 的跨端边云时序数据库架构与 AI 应用解析
  • SpringBoot SaaS 多租户架构与动态数据源配置解析
  • SpringBoot 开发环境搭建与配置
  • C++ 四叉树数据结构原理与实现
  • 前端拖拽交互实战:告别原生 API 的卡顿体验
  • Claude Code 安装指南(Windows / macOS)
  • LLaMA Factory 微调 LLMs 与 VLMs 实战指南
  • WeBASE 一键部署实战:Ubuntu 环境配置与常见问题解决
  • 基于 LangGraph 的 Python 记忆机器人:支持搜索工具与人工干预
  • C++98 实战:从零实现学生成绩管理系统
  • AIGC 辅助软件开发流程实践:测试管理系统构建
  • Stable Diffusion 云端部署:电商商用场景与成本透明化
  • 双指针算法实战:快乐数与盛最多水的容器
  • C++ 多态底层实现原理与内存布局解析
  • QGroundControl 跨平台部署指南:Windows、macOS、Linux 及 Android
  • OpenClaw 本地部署与飞书机器人接入指南
  • Flood Fill 算法实战:从图像渲染到岛屿问题

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online