1、开发环境:window10 + QtCreator4.8.2 + Qt5.12.2
2、开发背景:满足查看指定程序运行过程中的 CPU 使用情况
3、实现方法:
(1)通过程序名获取进程 ID
(2)获取 CPU 核心数量
(3)获取进程运行时间
(4)统计进程运行时的 CPU 使用率并保存
(5)实现代码和配置文件如下
//#include <stdafx.h>
#include <stdio.h>
#undef UNICODE
#include <windows.h>
#include <stdint.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <QFile>
#include <QDebug>
#include <QDateTime>
#include <QSettings>
#include <QCoreApplication>
using namespace std;
typedef long long int64_t;
typedef unsigned long long uint64_t;
// 时间转换
static uint64_t file_time_2_utc(const FILETIME* ftime)
{
LARGE_INTEGER li;
li.LowPart = ftime->dwLowDateTime;
li.HighPart = ftime->dwHighDateTime;
return li.QuadPart;
}
DWORD GetProcessIDByName(const char* pName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) {
return NULL;
}
PROCESSENTRY32 pe = { sizeof(pe) };
for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe))
{
if (strcmp(pe.szExeFile, pName) == 0)
{
CloseHandle(hSnapshot);
return pe.th32ProcessID;
}
printf("%-6d %s\n", pe.th32ProcessID, pe.szExeFile);
}
CloseHandle(hSnapshot);
return 0;
}
// 获得CPU的核数
static int get_processor_number()
{
SYSTEM_INFO info;
GetSystemInfo(&info);
return (int)info.dwNumberOfProcessors;
}
int get_cpu_usage(int pid)
{
//cpu数量
static int processor_count_ = -1;
//上一次的时间
static int64_t last_time_ = 0;
static int64_t last_system_time_ = 0;
FILETIME now;
FILETIME creation_time;
FILETIME exit_time;
FILETIME kernel_time;
FILETIME user_time;
int64_t system_time;
int64_t time;
int64_t system_time_delta;
int64_t time_delta;
int cpu = -1;
if(processor_count_ == -1)
{
processor_count_ = get_processor_number();
}
GetSystemTimeAsFileTime(&now);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if (!GetProcessTimes(hProcess, &creation_time, &exit_time, &kernel_time, &user_time))
{
return -1;
}
system_time = (file_time_2_utc(&kernel_time) + file_time_2_utc(&user_time))
/ processor_count_;
time = file_time_2_utc(&now);
if ((last_system_time_ == 0) || (last_time_ == 0))
{
last_system_time_ = system_time;
last_time_ = time;
return get_cpu_usage(pid);
}
system_time_delta = system_time - last_system_time_;
time_delta = time - last_time_;
if (time_delta == 0)
return get_cpu_usage(pid);
cpu = (int)((system_time_delta * 100 + time_delta / 2) / time_delta);
last_system_time_ = system_time;
last_time_ = time;
return cpu;
}
int main()
{
int cpu;
int process_id;
QString filePath = _pgmptr;
filePath.remove("testcpu.exe");
QString configPath = filePath + "/Setting.ini";
/* 全新文件模式 旧文件存在直接删掉 */
QFile fileConfig(configPath);
if (!fileConfig.exists())
{
qWarning() << __PRETTY_FUNCTION__ << "文件不存在:" << configPath;
return 0;
}
/* 文件生成 */
QSettings setting(configPath, QSettings::IniFormat);
setting.setIniCodec("UTF-8");
/* 通用组数据读取 */
setting.beginGroup("Process");
QString process_name = setting.value("process_name").toString();
process_name = process_name.split("#").first().simplified();
process_name.remove("'");
setting.endGroup();
setting.beginGroup("Interval");
QString interval_mString = setting.value("interval_m").toString();
interval_mString = interval_mString.split("#").first().simplified();
quint32 interval_m = interval_mString.toUInt();
setting.endGroup();
process_id = GetProcessIDByName(process_name.toLatin1());
qDebug() << __PRETTY_FUNCTION__ << "process_id:" << process_id
<< process_name << process_name.toLatin1();
if (process_id == 0)
{
qDebug() << __PRETTY_FUNCTION__ << "process_id abnormal:" << process_id;
return 0;
}
QString savePath = filePath += "/test.txt";
QFile fileSave(savePath);
fileSave.remove();
qDebug() << "savePath" << savePath;
while(1)
{
cpu = get_cpu_usage(process_id);
QString writeData = QString("%1 CPU: %2%")
.arg(QDateTime::currentDateTime().toString("[yyyy-MM-dd hh:mm:ss.zzz]"))
.arg(cpu, 2);
qDebug() << writeData;
fileSave.open(QIODevice::ReadWrite | QIODevice::Append);
fileSave.write(writeData.toLatin1() + "\n");
fileSave.flush();
fileSave.close();
Sleep(interval_m);
}
return 0;
}
[Process]
process_name = 'QQ.exe' # 进程名
[Interval]
interval_m = 1000 # 监测频率,以毫秒为单位