在Windows中计算CPU利用率的方法是使用SystemProcessorPerformanceInformation参数反复调用NtQuerySystemInformation函数,然后根据返回的IdleTime、KernelTime和UseTime值,分别使用后一次调用获得的值减去前一次调用获得的值,得到各个增量值,然后使用一个除法就可以得到CPU利用率。
这里唯一需要注意的是KernelTime成员值包含IdleTime和核心调用的使用时间。
当使用SystemBasicInformation 调用 NtQuerySystemInformation 来试图获取CPU个数时会失败,返回0xC0000004错误码,可以使用GetSystemInfo函数获得CPU的个数。
CPU利用率的计算公式如下:
100.0 * (IdleTime –PrevIdleTime) / (KernelTime + UserTime – PrevKernelTime – PrevUserTime)
注1:实际内核时间(ActualKernelTime)= KernelTime– IdleTime,内核时间-空闲时间。
注2:全部CPU时间(CpuTime)= UserTime +KernelTime,用户时间+内核时间。
CPP
#include "StdAfx.h"
#include "PUCoreUsage.h"
CPUCoreUsage::CPUCoreUsage(void)
{
m_iCPUCoreNum = GetCpuCoreNum();
printf("CPU Core Num:%d\n",m_iCPUCoreNum);
m_pCurcputimes = new SystemCpuTimes[m_iCPUCoreNum];
m_pNewcputimes = new SystemCpuTimes[m_iCPUCoreNum];
m_iCurValid = false;
}
CPUCoreUsage::~CPUCoreUsage(){
if (m_pCurcputimes)
delete m_pCurcputimes;
if (m_pNewcputimes)
delete m_pNewcputimes;
}
int CPUCoreUsage::GetCpuCoreNum(){
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
if( sysInfo.dwNumberOfProcessors <= 0){
return 1;
}
return sysInfo.dwNumberOfProcessors;
}
int CPUCoreUsage::GetSystemCpuTimes(SystemCpuTimes * cputimes, int num)
{
// dynamic linking is mandatory to use NtQuerySystemInformation
HINSTANCE hNtDll =LoadLibrary("ntdll.dll");
if (hNtDll == NULL) {
fprintf(stderr, "LoadLibraryntdll.dll failed.\n");
return -1;
}
// gets NtQuerySystemInformation address
NTQSI_PROC NtQuerySystemInformation =(NTQSI_PROC)GetProcAddress(hNtDll, "NtQuerySystemInformation");
if (NtQuerySystemInformation == NULL) {
FreeLibrary(hNtDll);
return -2;
}
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi
= new SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[num];
if (sppi == NULL) {
FreeLibrary(hNtDll);
return -3;
}
// Get CPU time informations
if (NtQuerySystemInformation(SystemProcessorPerformanceInformation,
sppi, num*
sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), NULL) != 0) {
FreeLibrary(hNtDll);
delete []sppi;
return -4;
}
// computes system global times summingeach processor value
for (DWORD i = 0; i <num; i++) {
cputimes[i].user = sppi[i].UserTime.QuadPart;
cputimes[i].kernal = sppi[i].KernelTime.QuadPart;
cputimes[i].idle = sppi[i].IdleTime.QuadPart;
cputimes[i].total = cputimes[i].user + cputimes[i].kernal;
}
FreeLibrary(hNtDll);
delete []sppi;
return 0;
}
int CPUCoreUsage::GetCPUCoreUsageInfo(double *usage ,int num)
{
if (num<m_iCPUCoreNum){
return -3;
}
if (NULL == usage){
return -2;
}
if (0 != GetSystemCpuTimes(m_pNewcputimes,m_iCPUCoreNum))
return -1;
if (!m_iCurValid){
SystemCpuTimes * temp = m_pNewcputimes;
m_pNewcputimes = m_pCurcputimes;
m_pCurcputimes = temp;
m_iCurValid = true;
return 1;
}
double total = 0;
int count = 0;
for (int i = 0; i < m_iCPUCoreNum; i++) {
if (m_pNewcputimes[i].total - m_pCurcputimes[i].total < 1000){
return -4;
}
usage[i] = 1.0f - (m_pNewcputimes[i].idle - m_pCurcputimes[i].idle)/
(m_pNewcputimes[i].total - m_pCurcputimes[i].total);
}
usage[m_iCPUCoreNum] = 1.0f - total/count;
{
SystemCpuTimes * temp = m_pNewcputimes;
m_pNewcputimes = m_pCurcputimes;
m_pCurcputimes = temp;
}
return 0;
}
H
class CPUCoreUsage
{
public:
CPUCoreUsage(void);
~CPUCoreUsage();
int GetCpuCoreNum();
int GetCPUCoreUsageInfo(double *usage ,int num);
int GetSystemCpuTimes(SystemCpuTimes * cputimes, int num);
private:
int m_iCPUCoreNum;
bool m_iCurValid;
SystemCpuTimes * m_pCurcputimes;
SystemCpuTimes * m_pNewcputimes;
};
int main()
{
CPUCoreUsage cpuCoreUsage;
SetProcessAffinityMask(GetCurrentProcess(),0x00000002);
int iCPUCoreNum = cpuCoreUsage.GetCpuCoreNum();
printf("CPU Core Num:%d\n",iCPUCoreNum);
double *usage = new double[iCPUCoreNum];
while(1){
int re = cpuCoreUsage.GetCPUCoreUsageInfo( usage , iCPUCoreNum);
if (re == 0){
double avgUsage = 0.0f;
printf("this pielod info:\n");
for(int i=0 ;i<iCPUCoreNum;i++){
avgUsage += usage[i];
printf("CPU%d : %f\n",i,usage[i]);
}
avgUsage /= iCPUCoreNum;
printf(" Avg CPU : %f\n",avgUsage);
}else{
printf("result %d\n",re);
}
Sleep(200);
}
return 0;
}