[已解决][求助]如何获取 CPU 实时频率?
2023-10-21 751

1.webp

如图,如何获取和任务管理器上显示一致的 CPU 实时频率?(不用 WMI 或性能计数器)

已知使用性能计数器

\Processor Information(_Total)\% Processor Performance * 基准频率 / 100

可以获得实时频率,现在希望不通过性能计数器获取这个数据,谢谢。

最后于 15小时前 被a1ive编辑 ,原因:
奖励
收藏
点赞
分享
最新回复 (3)
  • avatar image
    爱心会员VIP会员
    527104427 2023-10-21

    我能查到的也只有通过性能计数器或WMI获取。建议读一下systeminformer的源码,估计能找到思路。

    https://www.123pan.com/s/NflRVv-Cm5Sh
  • avatar image
    a1ive 2023-10-21
    楼主   3
    527104427 我能查到的也只有通过性能计数器或WMI获取。建议读一下systeminformer的源码,估计能找到思路。

    感谢回复。我研究一下。

  • avatar image
    a1ive 14小时前
    楼主   4
    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平均值即可。

     

    从Win10某一版本开始, CurrentMhz变为无效值。

    需要使用 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;
返回