通過C++獲取CPU占用率的代碼示例(windows、linux、macOS)
獲取CPU占用率
windows平臺

在Windows系統(tǒng)下使用C++獲取CPU占用率,常見方法可分為系統(tǒng)整體占用率和特定進程占用率兩類。以下是具體實現(xiàn)方法及核心代碼示例:
一、獲取系統(tǒng)整體CPU占用率
方法1:基于GetSystemTimes函數(shù)
原理:通過計算兩次采樣的系統(tǒng)空閑時間、內(nèi)核時間和用戶時間差值,結(jié)合公式得出整體CPU使用率。
#include <windows.h>
#include <iostream>
double GetCpuUsage() {
FILETIME idleTime, kernelTime, userTime;
static FILETIME preIdleTime, preKernelTime, preUserTime;
GetSystemTimes(&idleTime, &kernelTime, &userTime);
// 轉(zhuǎn)換為64位整型
ULONGLONG idle = (*(ULONGLONG*)&idleTime) - (*(ULONGLONG*)&preIdleTime);
ULONGLONG kernel = (*(ULONGLONG*)&kernelTime) - (*(ULONGLONG*)&preKernelTime);
ULONGLONG user = (*(ULONGLONG*)&userTime) - (*(ULONGLONG*)&preUserTime);
preIdleTime = idleTime;
preKernelTime = kernelTime;
preUserTime = userTime;
if (kernel + user == 0) return 0.0;
return ((kernel + user - idle) * 100.0) / (kernel + user);
}
// 調(diào)用示例
int main() {
while (true) {
Sleep(1000); // 間隔1秒采樣
std::cout << "CPU Usage: " << GetCpuUsage() << "%" << std::endl;
}
return 0;
}
- 關(guān)鍵點:
需間隔一定時間(如1秒)采樣兩次數(shù)據(jù)。
公式:(內(nèi)核時間 + 用戶時間 - 空閑時間) / (內(nèi)核時間 + 用戶時間)。
方法2:使用性能計數(shù)器(PDH庫)
適用場景:需要高精度或?qū)崟r監(jiān)控多個計數(shù)器。
#include <windows.h>
#include <pdh.h>
#pragma comment(lib, "pdh.lib")
double GetCpuUsageByPdh() {
static PDH_HQUERY query;
static PDH_HCOUNTER counter;
static bool initialized = false;
if (!initialized) {
PdhOpenQuery(nullptr, 0, &query);
PdhAddCounter(query, L"\\Processor(_Total)\\% Processor Time", 0, &counter);
initialized = true;
}
PDH_FMT_COUNTERVALUE value;
PdhCollectQueryData(query);
PdhGetFormattedCounterValue(counter, PDH_FMT_DOUBLE, nullptr, &value);
return value.doubleValue;
}
- 優(yōu)點:與任務(wù)管理器數(shù)據(jù)一致,支持多核統(tǒng)計。
二、獲取特定進程CPU占用率
原理:通過GetProcessTimes獲取進程的內(nèi)核和用戶時間,計算兩次采樣的時間差占比。
#include <windows.h>
#include <iostream>
class ProcessCpuMonitor {
public:
ProcessCpuMonitor(DWORD pid) : pid_(pid) {
hProcess_ = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid_);
}
~ProcessCpuMonitor() {
if (hProcess_) CloseHandle(hProcess_);
}
float GetUsage() {
FILETIME createTime, exitTime, kernelTime, userTime;
if (!GetProcessTimes(hProcess_, &createTime, &exitTime, &kernelTime, &userTime))
return -1;
ULONGLONG currentKernel = *(ULONGLONG*)&kernelTime;
ULONGLONG currentUser = *(ULONGLONG*)&userTime;
ULONGLONG delta = (currentKernel + currentUser) - (lastKernel_ + lastUser_);
// 計算時間差(單位:100納秒)
ULONGLONG timePassed = GetTickCount64() - lastTick_;
lastTick_ = GetTickCount64();
lastKernel_ = currentKernel;
lastUser_ = currentUser;
if (timePassed == 0) return 0.0f;
return (delta / 10000.0f) / timePassed * 100.0f; // 轉(zhuǎn)換為百分比
}
private:
DWORD pid_;
HANDLE hProcess_ = nullptr;
ULONGLONG lastKernel_ = 0, lastUser_ = 0;
ULONGLONG lastTick_ = 0;
};
// 調(diào)用示例
int main() {
DWORD pid = 1234; // 目標(biāo)進程ID
ProcessCpuMonitor monitor(pid);
while (true) {
Sleep(1000);
std::cout << "Process CPU Usage: " << monitor.GetUsage() << "%" << std::endl;
}
return 0;
}
注意事項:
需以PROCESS_QUERY_LIMITED_INFORMATION權(quán)限打開進程。
公式:(進程時間差 / 系統(tǒng)時間差) * 100%。
三、常見問題
- 與任務(wù)管理器數(shù)據(jù)不一致:因采樣間隔和計算方式差異,結(jié)果可能有輕微偏差。
- 多核CPU:上述方法返回的是整體利用率,如需單核數(shù)據(jù),需遍歷每個邏輯處理器。
- 權(quán)限問題:獲取系統(tǒng)級數(shù)據(jù)需管理員權(quán)限,進程級數(shù)據(jù)則不需要。
linux平臺
在Linux系統(tǒng)下使用C++獲取CPU占用率,主要通過解析/proc/stat文件實現(xiàn)。以下是具體實現(xiàn)方法和原理說明:
一、核心原理
Linux內(nèi)核通過/proc/stat文件提供CPU活動的統(tǒng)計信息。文件中記錄了從系統(tǒng)啟動到當(dāng)前時刻,CPU在不同狀態(tài)下的累計時間(單位:時鐘周期),包括:
- user:用戶態(tài)執(zhí)行時間
- nice:低優(yōu)先級用戶態(tài)時間
- system:內(nèi)核態(tài)執(zhí)行時間
- idle:空閑時間
- iowait:I/O等待時間
- irq:硬件中斷時間
- softirq:軟件中斷時間
通過兩次采樣這些數(shù)值,計算時間差并分析CPU占用率。
二、實現(xiàn)步驟
讀取 /proc/stat 文件
#include <fstream>
#include <vector>
#include <string>
struct CpuTime {
unsigned long user, nice, system, idle, iowait, irq, softirq;
};
CpuTime readCpuStats() {
std::ifstream file("/proc/stat");
std::string cpu_label;
CpuTime time;
file >> cpu_label >> time.user >> time.nice >> time.system >> time.idle
>> time.iowait >> time.irq >> time.softirq;
return time;
}
- 計算CPU使用率
通過兩次采樣時間差計算CPU利用率:
double calculateCpuUsage(const CpuTime& prev, const CpuTime& curr) {
const unsigned long prev_total = prev.user + prev.nice + prev.system + prev.idle
+ prev.iowait + prev.irq + prev.softirq;
const unsigned long curr_total = curr.user + curr.nice + curr.system + curr.idle
+ curr.iowait + curr.irq + curr.softirq;
const unsigned long total_diff = curr_total - prev_total;
const unsigned long idle_diff = curr.idle - prev.idle;
return (total_diff - idle_diff) * 100.0 / total_diff;
}
- 完整示例
#include <iostream>
#include <unistd.h>
int main() {
CpuTime prev = readCpuStats();
sleep(1); // 采樣間隔1秒
CpuTime curr = readCpuStats();
double usage = calculateCpuUsage(prev, curr);
std::cout << "CPU Usage: " << usage << "%" << std::endl;
return 0;
}
三、擴展說明
多核CPU處理
/proc/stat中每行對應(yīng)一個CPU核心(如cpu0, cpu1),需分別解析。
進程級CPU占用率
通過讀取/proc/[pid]/stat獲取進程的utime(用戶態(tài)時間)和stime(內(nèi)核態(tài)時間),結(jié)合系統(tǒng)總時間計算。
注意事項
采樣間隔建議≥1秒,避免瞬時波動。
需處理/proc文件讀取失敗的情況。
高精度場景可使用clock_gettime替代sleep。
四、優(yōu)化與替代方案
使用 sysinfo 系統(tǒng)調(diào)用
獲取粗略的系統(tǒng)負(fù)載信息,但精度較低。
調(diào)用 getrusage 函數(shù)
適用于統(tǒng)計進程自身的CPU使用情況。
第三方庫
如libstatgrab或procps-ng提供封裝接口。
macOS平臺
在 macOS 系統(tǒng)下通過 C++ 獲取 CPU 占用率,需要調(diào)用 Mach 內(nèi)核 API 實現(xiàn)。以下是基于 、、 等資料的實現(xiàn)方案:
一、核心實現(xiàn)原理
Mach API 調(diào)用
macOS 基于 Darwin 內(nèi)核,通過 <mach/mach_host.h> 提供的 host_statistics 函數(shù)獲取 CPU 時間統(tǒng)計信息。
CPU 占用率計算
需兩次采樣間隔內(nèi)的 CPU 使用時間差,公式:
CPU 占用率 = (用戶態(tài)時間 + 內(nèi)核態(tài)時間) / (總時間差) * 100%
二、代碼實現(xiàn)示例
#include <mach/mach_host.h>
#include <mach/processor_info.h>
#include <unistd.h>
double get_cpu_usage() {
host_cpu_load_info_data_t cpuinfo;
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
kern_return_t kr = host_statistics(mach_host_self(),
HOST_CPU_LOAD_INFO,
(host_info_t)&cpuinfo,
&count);
if (kr != KERN_SUCCESS) return -1.0;
// 第一次采樣
uint64_t total_user_prev = cpuinfo.cpu_ticks[CPU_STATE_USER];
uint64_t total_sys_prev = cpuinfo.cpu_ticks[CPU_STATE_SYSTEM];
uint64_t total_idle_prev = cpuinfo.cpu_ticks[CPU_STATE_IDLE];
uint64_t total_used_prev = total_user_prev + total_sys_prev;
// 等待 1 秒后再次采樣
sleep(1);
kr = host_statistics(mach_host_self(),
HOST_CPU_LOAD_INFO,
(host_info_t)&cpuinfo,
&count);
if (kr != KERN_SUCCESS) return -1.0;
uint64_t total_user = cpuinfo.cpu_ticks[CPU_STATE_USER];
uint64_t total_sys = cpuinfo.cpu_ticks[CPU_STATE_SYSTEM];
uint64_t total_idle = cpuinfo.cpu_ticks[CPU_STATE_IDLE];
uint64_t total_used = total_user + total_sys;
// 計算差值
uint64_t used_diff = total_used - total_used_prev;
uint64_t idle_diff = total_idle - total_idle_prev;
uint64_t total_diff = used_diff + idle_diff;
return (total_diff == 0) ? 0 : (used_diff * 100.0) / total_diff;
}
三、關(guān)鍵點說明
多核 CPU 處理
上述代碼返回的是 所有 CPU 核心的平均占用率。若需獲取單核數(shù)據(jù),需通過 host_processor_info 函數(shù)遍歷每個核心 。
時間間隔選擇
兩次采樣間隔建議 1 秒(sleep(1)),間隔過短會導(dǎo)致誤差增大。
錯誤處理
檢查 host_statistics 返回值是否為 KERN_SUCCESS,避免因權(quán)限問題或 API 調(diào)用失敗導(dǎo)致崩潰。
四、擴展功能
獲取單進程 CPU 占用
結(jié)合 proc_pidinfo 函數(shù)和 PROC_PIDTASKINFO 參數(shù),可獲取指定進程的 CPU 時間 。
實時監(jiān)控
通過多線程循環(huán)調(diào)用上述函數(shù),實現(xiàn)動態(tài)曲線繪制(參考 中的 ImGui 方案)。
五、編譯注意事項
頭文件依賴:需包含 <mach/mach.h> 和 <mach/mach_host.h>
鏈接框架:添加 -framework IOKit 編譯選項
示例:clang++ -framework IOKit cpu_usage.cpp -o cpu_usage
以上就是通過C++獲取CPU占用率的代碼示例(windows、linux、macOS)的詳細內(nèi)容,更多關(guān)于C++獲取CPU占用率的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++ 內(nèi)存分配處理函數(shù)set_new_handler的使用
這篇文章主要介紹了C++ 內(nèi)存分配處理函數(shù)set_new_handler的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
C語言 TerminateProcess函數(shù)案例詳解
這篇文章主要介紹了C語言 TerminateProcess函數(shù)案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08
C語言中帶頭雙向循環(huán)鏈表基本操作的實現(xiàn)詳解
無頭單向非循環(huán)鏈表結(jié)構(gòu)簡單,一般不會單獨用來存數(shù)據(jù)。而帶頭雙向循環(huán)鏈表的結(jié)構(gòu)較為復(fù)雜,一般用在單獨存儲數(shù)據(jù)。本文將介紹帶頭雙向循環(huán)鏈表的基本操作,需要的可以參考一下2022-11-11
Qt串口通信開發(fā)之QSerialPort模塊詳細使用方法與實例
這篇文章主要介紹了Qt串口通信開發(fā)之QSerialPort模塊詳細使用方法與實例,需要的朋友可以參考下2020-03-03

