我想要实现的是获取每个CPU的利用率(我有4个CPU核心,所以我希望像在
resmon.exe
中一样能够获取它们所有的利用率)以及它们的总和(就像在TaskManager.exe
中一样)。
我在某些来源上读到,获取处理器利用率的方法是对CPU时间进行数学计算。我尝试使用NtQuerySystemInformation
获取必要的数据。
#include <windows.h>
#include <vector>
#include <iostream>
#include <winternl.h>
#pragma comment(lib, "Ntdll.lib")
typedef struct
_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R {
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER DpcTime;
LARGE_INTEGER InterruptTime;
ULONG InterruptCount;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R;
static long long toInteger(LARGE_INTEGER const & integer)
{
#ifdef INT64_MAX // Does the compiler natively support 64-bit integers?
return integer.QuadPart;
#else
return (static_cast<long long>(integer.HighPart) << 32) | integer.LowPart;
#endif
}
class CPU
{
public:
uint64_t prev_idle = 0;
uint64_t prev_ker = 0;
uint64_t prev_user = 0;
uint64_t cur_idle = 0;
uint64_t cur_ker = 0;
uint64_t cur_user = 0;
double get()
{
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R *a = new SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R[4];
// 4 is the total of CPU (4 cores)
NtQuerySystemInformation(SystemProcessorPerformanceInformation, a, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R) * 4, NULL);
prev_idle = cur_idle;
prev_ker = cur_ker;
prev_user = cur_user;
cur_idle = 0;
cur_ker = 0;
cur_user = 0;
// 4 is the total of CPU (4 cores)
// Sum up the SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R array so I can get the utilization from all of the CPU
for (int i = 0; i < 4; ++i)
{
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R b = a[i];
cur_idle += toInteger(b.IdleTime);
cur_ker += toInteger(b.KernelTime);
cur_user += toInteger(b.UserTime);
}
std::cout << "Cur idle " << cur_idle << '\n';
std::cout << "Cur ker " << cur_ker << '\n';
std::cout << "Cur user " << cur_user << '\n';
uint64_t delta_idle = cur_idle - prev_idle;
uint64_t delta_kernel = cur_ker - prev_ker;
uint64_t delta_user = cur_user - prev_user;
std::cout << "Delta idle " << delta_idle << '\n';
std::cout << "Delta ker " << delta_kernel << '\n';
std::cout << "Delta user " << delta_user << '\n';
uint64_t total_sys = delta_kernel + delta_user;
uint64_t kernel_total = delta_kernel - delta_idle;
delete[] a;
// return (total_sys - delta_idle) * 100.0 / total_sys;
return (kernel_total + delta_user) * 100.0 / total_sys;
}
};
int main()
{
CPU a;
std::cout << "starting" << '\n';
while(1)
{
std::cout << a.get() << '\n';
Sleep(1000);
}
return 0;
}
为了获取单个CPU的利用率,我不必将所有CPU求和,只需选择一个SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R
数组元素即可。
我的问题是:
- 我做得对吗?因为当我使用任务管理器中的CPU利用率检查我的程序时,结果有些不同。
- 除了使用
NtQuerySystemInformation
,是否还有更好的方法(因为微软已经提到“NtQuerySystemInformation可能在未来的Windows版本中被更改或取消。应用程序应该使用本主题中列出的替代函数。”)?
GetSystemTimes
替代,以检索此信息。 - Drake WuWin32_PerfRawData_PerfOS_Processor
和 原始性能数据类 吗?顺便说一下,我已经测试了NtQuerySystemInformation
和GetSystemTimes
,它们对我来说返回的值是相同的。 - Drake WuNtQuerySystemInformation
和GetSystemTimes
可以产生相同的结果,但是NtQuerySystemInformation
提供了更多的细节,需要自己进行求和。 - AndraWin32_PerfRawData_PerfOS_Processor
将为您提供系统中每个逻辑 CPU 的一个“行”/“条目”。例如,在我的计算机上,我有 12 个逻辑 CPU,并查询此类将给我 12 个结果(分别为Name
0 到 12)。另外,任务管理器也可以显示单个逻辑 CPU。右键单击图表,从上下文菜单中选择“更改图形类型”。 - Christian.K