如图,如何获取和任务管理器上显示一致的 CPU 实时频率?(不用 WMI 或性能计数器)
已知使用性能计数器
\Processor Information(_Total)\% Processor Performance * 基准频率 / 100
可以获得实时频率,现在希望不通过性能计数器获取这个数据,谢谢。
我能查到的也只有通过性能计数器或WMI获取。建议读一下systeminformer的源码,估计能找到思路。
527104427 我能查到的也只有通过性能计数器或WMI获取。建议读一下systeminformer的源码,估计能找到思路。
感谢回复。我研究一下。
此问题已解决。
对于Win10以前的版本,可以通过CallNtPowerInformation来获取实时频率。
typedef struct { ULONG Number; ULONG MaxMhz; ULONG CurrentMhz; ULONG MhzLimit; ULONG MaxIdleState; ULONG CurrentIdleState; } PROCESSOR_POWER_INFORMATION; SYSTEM_INFO sys; GetSystemInfo(&sys); BYTE* buf = (BYTE*)calloc(sys.dwNumberOfProcessors, sizeof(PROCESSOR_POWER_INFORMATION)); CallNtPowerInformation(ProcessorInformation, NULL, 0, buf, sizeof(PROCESSOR_POWER_INFORMATION) * sys.dwNumberOfProcessors);
遍历PROCESSOR_POWER_INFORMATION 数组,取得 CurrentMhz平均值即可。
PROCESSOR_POWER_INFORMATION
CurrentMhz
从Win10某一版本开始, CurrentMhz变为无效值。
需要使用 NtQuerySystemInformation 获取 SYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION 结构体,计算过程很复杂。
NtQuerySystemInformation
SYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION
Win10以前的版本如Win8也可以用此方法,但是结构体各字段位置有点不一样,太麻烦了。
伪代码:
typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_HITCOUNT { ULONGLONG Hits; UCHAR PercentFrequency; } SYSTEM_PROCESSOR_PERFORMANCE_HITCOUNT, * PSYSTEM_PROCESSOR_PERFORMANCE_HITCOUNT; typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_STATE_DISTRIBUTION { ULONG ProcessorNumber; ULONG StateCount; SYSTEM_PROCESSOR_PERFORMANCE_HITCOUNT States[1]; } SYSTEM_PROCESSOR_PERFORMANCE_STATE_DISTRIBUTION, * PSYSTEM_PROCESSOR_PERFORMANCE_STATE_DISTRIBUTION; typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION { ULONG ProcessorCount; ULONG Offsets[1]; } SYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION, * PSYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION; PSYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION old_ppd, new_ppd; SystemProcessorPerformanceDistribution = 110; NtQuerySystemInformation(SystemProcessorPerformanceDistribution, new_ppd, len, &len); ULONGLONG total_hits_delta = 0; ULONGLONG total_freq_contrib = 0; for (i = 0; i < num_of_cpu; i++) { PSYSTEM_PROCESSOR_PERFORMANCE_STATE_DISTRIBUTION old_state, new_state; new_state = new_ppd + new_ppd->Offsets[i]; old_state = old_ppd + old_ppd->Offsets[i]; for (j = 0; j < new_state->StateCount; j++) { ULONGLONG hits_delta = new_state->State[j].Hits - old_state->State[j].Hits; total_hits_delta += hits_delta; total_freq_contrib += hits_delta * new_state->States[j].PercentFrequency * max_mhz; } } old_ppd = new_ppd; return total_freq_contrib / total_hits_delta / 100;