Qt获取CPU使用率及内存占用大小
Qt 获取 CPU 使用率及内存占用大小
文章目录
- Qt 获取 CPU 使用率及内存占用大小
- 一、简介
- 二、关键函数
- 2.1 获取当前运行程序pid
- 2.2 通过pid获取运行时间
- 2.3 通过pid获取内存大小
- 三、具体实现
- 五、写在最后
一、简介
近期在使用软件的过程中发现一个有意思的东西。如下所示:
该软件可以显示 CPU
使用率及内存大小和内存使用率。感觉比较有意思,于是就想着能不能通过 Qt
自己实现一套这样的东西,这也是本文的由来。
那么,言归正传,本文将介绍 如何使用 Qt
获取当前软件的 CPU
使用率及内存大小。本文适合对 Qt
有一些基础的朋友,对于一些简单的地方我不会过多赘述,望谅解!!!
另外,本文阐述方法不适用于 Linux
,需要注意!!!
首先,我使用的环境如下所示:
- Windows 10 x64
- Qt 5.12.3
二、关键函数
本文专注于解决获取 Qt
当前运行程序的 CPU
使用率及内存大小,因此本文通过获取当前运行程序 pid
的形式获取运行时间,通过运行时间计算得到 CPU
使用率。
2.1 获取当前运行程序pid
在 Qt
中,可以通过如下所示的语句获取当前程序 PID
:
QApplication::applicationPid();
2.2 通过pid获取运行时间
首先,需要打开进程句柄,需要使用到如下所示的函数:
HANDLE OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId
);
其中三个参数意义如下所示:
dwDesiredAccess
: 进程访问权限bInheritHandle
: 是否允许子进程继承此句柄,通常设为FALSE
dwProcessId
: 目标进程的PID
(进程标识符)
返回值意义如下所示:
- 成功:返回进程句柄(
HANDLE
) - 失败:返回
NULL
,需调用GetLastError()
获取错误码
更详细的解释在官方网站:OpenProcess 函数 (processthreadsapi.h) - Win32 apps | Microsoft Learn
如若链接点击无法跳转,可自行复制打开:
- https://learn.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess
其次,我们需要通过 PID
获取运行时间信息,需要使用到如下所示的函数:
BOOL GetProcessTimes(HANDLE hProcess,LPFILETIME lpCreationTime,LPFILETIME lpExitTime,LPFILETIME lpKernelTime,LPFILETIME lpUserTime
);
其参数意义如下所示:
hProcess
: 进程句柄lpCreationTime
: 进程的创建时间lpExitTime
: 进程的退出时间lpKernelTime
: 内核模式(如系统调用)下消耗的CPP
时间lpUserTime
: 用户模式(应用程序代码)下消耗的CPU
时间
返回参数意义如下所示:
- 成功:返回
TRUE
(非零值) - 失败:返回
FALSE
(零值),需调用GetLastError()
获取错误码
更详细的解释在官方网站:getProcessTimes 函数 (processthreadsapi.h) - Win32 apps | Microsoft Learn
如若链接点击无法跳转,可自行复制打开:
- https://learn.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocesstimes
2.3 通过pid获取内存大小
获取进程使用内存大小,需要使用如下所示函数:
BOOL GetProcessMemoryInfo(HANDLE Process, PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb
);
其参数意义如下所示:
Process
: 进程句柄ppsmemCounters
: 指向PROCESS_MEMORY_COUNTERS
结构的指针,用于接收内存统计信息cb
: 结构体大小,通常设为sizeof(PROCESS_MEMORY_COUNTERS)
返回参数意义如下所示:
- 成功:返回
TRUE
(非零值) - 失败:返回
FALSE
(零值),需调用GetLastError()
获取错误码
其中需要注意的是 PROCESS_MEMORY_COUNTERS
结构体,其包含如下所示的成员参数:
typedef struct _PROCESS_MEMORY_COUNTERS {DWORD cb; // 结构体大小DWORD PageFaultCount; // 页面错误次数SIZE_T PeakWorkingSetSize; // 工作集峰值(物理内存)SIZE_T WorkingSetSize; // 当前工作集大小SIZE_T QuotaPeakPagedPoolUsage; // 分页池配额峰值SIZE_T QuotaPagedPoolUsage; // 当前分页池配额SIZE_T QuotaPeakNonPagedPoolUsage; // 非分页池配额峰值SIZE_T QuotaNonPagedPoolUsage; // 当前非分页池配额SIZE_T PagefileUsage; // 页面文件使用量SIZE_T PeakPagefileUsage; // 页面文件使用峰值
} PROCESS_MEMORY_COUNTERS;
更详细的解释在官方网站:getProcessMemoryInfo 函数 (psapi.h) - Win32 apps | Microsoft Learn
如若链接点击无法跳转,可自行复制打开:
- https://learn.microsoft.com/zh-cn/windows/win32/api/psapi/nf-psapi-getprocessmemoryinfo
通过上述三个步骤即可轻松获取当前运行程序的 CPU
使用率及内存大小。
三、具体实现
在 Qt
中推荐在线程中计算获取这些信息。因为我们计算方法每 1s 获取一次时间,计算与前 1s 时间的差值得到 CPU
占用率。如果不适用线程,将会阻塞主线程的执行。
这里我给出示例:
-
cpumontior.h
#ifndef CPUMONTIOR_H #define CPUMONTIOR_H#include "windows.h" #include <QObject> #include <QThread> #include "psapi.h" #include <QtMath>class CpuMontior : public QThread {Q_OBJECT public:explicit CpuMontior(DWORD pid, QObject *parent = nullptr);void setDec(int dec) {this->dec = dec;}protected:void run() override;private:DWORD pid;int dec;// 封装转换函数static ULONGLONG filetimeToULONGLONG(const FILETIME *ft) {ULARGE_INTEGER uli;uli.LowPart = ft->dwLowDateTime;uli.HighPart = ft->dwHighDateTime;return uli.QuadPart;}// bytes 单位转换QString changeFileSize(qint64 fileSize){QStringList units;units << "B" << "KB" << "MB" << "GB" << "TB" << "PB";double mod = 1024.0;double size = fileSize;//qDebug() << size;int i = 0;long rest = 0;while (size >= mod && i < units.count()-1 ){rest= static_cast<long>(size) % static_cast<long>(mod);size /= mod;i++;}QString szResult = QString::number(qFloor(size));if( rest > 0){szResult += QString(".") + QString::number(rest).left(this->dec);}szResult += units[i];return szResult;}signals:/* 使用率信息 */void usageInfoSignal(QString cpuUsage, QString memUsage);public slots: };#endif // CPUMONTIOR_H
-
cpumontior.cpp
#include "cpumontior.h" #ifdef QT_DEBUG #include <QDebug> #endif/*!* @File : cpumontior.cpp* @Brief : 构造函数* @Details : None* @Param : void* @Return : void* @Author : Liu Jiahao* @Date : 2025-03-28 14:18:10* @Version : v1.1* @Copyright : Copyright By Liu Jiahao, All Rights Reserved**/ CpuMontior::CpuMontior(DWORD pid, QObject *parent) :QThread(parent), pid(pid), dec(2) {}/*!* @File : cpumontior.cpp* @Brief : 工作函数* @Details : None* @Param : void* @Return : void* @Author : Liu Jiahao* @Date : 2025-03-28 14:19:12* @Version : v1.1* @Copyright : Copyright By Liu Jiahao, All Rights Reserved**/ void CpuMontior::run() {// 获取系统资源信息HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);if (!hProcess) return;FILETIME creationTime, exitTime, kernelTime, userTime;while (!isInterruptionRequested()) {// 第一次采样if (!GetProcessTimes(hProcess, &creationTime, &exitTime, &kernelTime, &userTime)) {break;}ULONGLONG kernel1 = filetimeToULONGLONG(&kernelTime);ULONGLONG user1 = filetimeToULONGLONG(&userTime);msleep(1000); // 每秒更新一次// 第二次采样if (!GetProcessTimes(hProcess, &creationTime, &exitTime, &kernelTime, &userTime)) {break;}ULONGLONG kernel2 = filetimeToULONGLONG(&kernelTime);ULONGLONG user2 = filetimeToULONGLONG(&userTime);// 计算差值ULONGLONG totalTime = (kernel2 - kernel1) + (user2 - user1);double cpuUsage = (totalTime / 10000.0) / 100.0; // 转换为百分比// 内存使用率PROCESS_MEMORY_COUNTERS pmc;qint64 memoryUsage = 0;if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {memoryUsage = static_cast<qint64>(pmc.WorkingSetSize); // 单位:字节}// 通过信号发送emit usageInfoSignal(QString::number(cpuUsage, 'f', this->dec) + "%", changeFileSize(memoryUsage));} #ifdef QT_DEBUGqDebug() << "quit thread"; #endifCloseHandle(hProcess); }
增加 UI
进行显示后,效果如下所示:
可以说,跟我开头放的那个图区别不大。具体的 UI
设计这里不进行赘述,大家可以自行构建。我在函数中使用了 emit usageInfoSignal(QString::number(cpuUsage, 'f', this->dec) + "%", changeFileSize(memoryUsage));
发送信号,大家可以根据这个信号 connect
槽函数进行实现。
五、写在最后
本文介绍了 如何使用 Qt
获取当前软件的 CPU
使用率及内存大小。
题外话,现在觉得
AI
已经可以解决大部分遇到的问题,本文代码部分也借助了AI
帮助,所有功能并非我原创。其实我也很惋惜,大家可以自行通过AI
解决这些问题,就不需要在网上到处搜索,那我写博文似乎也失去了意义… 人工智能的发展不是坏事,只是改变了一些我们思考问题、解决问题的习惯。同时我也并不觉得 csdn 这个平台有多好,也未经过我同意擅自将我的文章设置为仅VIP可见,这与我初心相悖。随着工作繁忙,也很少有时间继续写下去…渐渐地也没有了动力。下次更新不知道是什么时候,希望读者海涵!
欢迎广大读者提出问题以及修改意见,本人看到后会给予回应,欢迎留言,后续会逐步进行开源!!!
另外,由于文章是作者手打的文字,有些地方可能文字会出错,望谅解,也可私信联系我,我对其进行更改。
-
个人CSDN账号:刘梓谦_-CSDN博客
-
Gitee:刘佳豪 (liu-jiahaohappy) - Gitee.com
-
GitHub:Jiahao-Liu29 (github.com)