显示每个进程CPU利用率——Windows,VC(2)

本文介绍了如何在Windows环境下,使用VC编写程序来计算每个进程的CPU利用率。通过调用NtQuerySystemInformation API获取系统信息,结合结构体定义,实时计算并展示特定进程的CPU占用情况。代码已在Windows XP和VC 6.0上测试通过。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家好,今天我来说一下显示每个进程CPU利用率的问题,

说实话,我的毕业设计作的就是这个,搜遍了网上也没有几个合适的答案,最后功夫不负有心人让我找到了一位高手的程序,原文是这样的,

以进程的ID作为参数,进程CPU占用率作为返回值,实时计算特定进程的CPU占用,测试正确。整个程序如下:

结构定义:
typedef struct _THREAD_INFO
{
LARGE_INTEGER CreateTime;
DWORD dwUnknown1;
DWORD dwStartAddress;
DWORD StartEIP;
DWORD dwOwnERPID;
DWORD dwThreadId;
DWORD dwCurrentPriority;
DWORD dwBasePriority;
DWORD dwContextSwitches;
DWORD Unknown;
DWORD WaitReason;

}THREADINFO, *PTHREADINFO;

typedef struct _UNICODE_STRING
{
 USHORT Length;
 USHORT MaxLength;
 PWSTR Buffer;
} UNICODE_STRING;

typedef struct _PROCESS_INFO
{
DWORD dwOffset;
DWORD dwThreadsCount;
DWORD dwUnused1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;

DWORD dwBasePriority;
DWORD dwProcessID;
DWORD dwParentProcessId;
DWORD dwHandleCount;
DWORD dwUnused3[2];

DWORD dwVirtualBytesPeak;
DWORD dwVirtualBytes;
ULONG dwPageFaults;
DWORD dwWorkingSetPeak;
DWORD dwWorkingSet;
DWORD dwQuotaPeakPagedPoolUsage;
DWORD dwQuotaPagedPoolUsage;
DWORD dwQuotaPeakNonPagedPoolUsage;
DWORD dwQuotaNonPagedPoolUsage;
DWORD dwPageFileUsage;
DWORD dwPageFileUsagePeak;

DWORD dCommitCharge;
THREADINFO ThreadSysInfo[1];

} PROCESSINFO, *PPROCESSINFO;

函数定义:

int Button2Click(int id);//参数是进程ID

函数实体:
int Button2Click(int id)
{
int cpuusage;
PVOID pProcInfo = NULL;
DWORD dwInfoSize = 0x20000;
PPROCESSINFO pProcessInfo;
DWORD dwWorkingSet;
long ( __stdcall *NtQuerySystemInformation )( DWORD, PVOID, DWORD, DWORD );


static __int64 LastTotalProcessCPUUsage = 0;
static __int64 LastCurrentProcessCPUUsage = 0;

int CurrentDelta;
int TotalDelta;

__int64 TotalProcessCPUUsage = 0;
__int64 CurrentProcessCPUUsage = 0;

/////////////////////////////////

pProcInfo = (PVOID)(new byte[dwInfoSize]);

NtQuerySystemInformation = (long(__stdcall*)(DWORD,PVOID,DWORD,DWORD))
GetProcAddress( GetModuleHandle( "ntdll.dll" ),"NtQuerySystemInformation" );

NtQuerySystemInformation(5,pProcInfo,dwInfoSize,0);

pProcessInfo = (PPROCESSINFO)pProcInfo;

do
{
TotalProcessCPUUsage += (__int64)pProcessInfo->KernelTime.QuadPart + (__int64)pProcessInfo->UserTime.QuadPart;

if(pProcessInfo->dwProcessID == id)
{
dwWorkingSet = pProcessInfo->dwWorkingSet;
CurrentProcessCPUUsage += (__int64)pProcessInfo->KernelTime.QuadPart + (__int64)pProcessInfo->UserTime.QuadPart;
}

/////////
if(pProcessInfo->dwOffset == 0)
{
break;
}

pProcessInfo = (PPROCESSINFO)((byte*)pProcessInfo + pProcessInfo->dwOffset);
}
while(true);

TotalDelta = TotalProcessCPUUsage - LastTotalProcessCPUUsage;
CurrentDelta = CurrentProcessCPUUsage - LastCurrentProcessCPUUsage;

if(TotalDelta != 0)
cpuusage = 100 * CurrentDelta / TotalDelta;

//this->Caption = "CPU = " + IntToStr(100 * CurrentDelta / TotalDelta) +
//"Memory = "+ IntToStr(dwWorkingSet / 1024) " K";

LastTotalProcessCPUUsage = TotalProcessCPUUsage;
LastCurrentProcessCPUUsage = CurrentProcessCPUUsage;

delete[] pProcInfo;
return cpuusage;

}


控制台调用:
int main(void)
{
 while(true)
 {
  int s = Button2Click(0);//在此把进程ID作为参数传入
  printf("%d/n",s);
  Sleep(1000);
 }
 return 0;
}
///////////////////////////////
以上代码运行非常正常
/////////////////////////////// 

希望能对你有些帮助,但我的毕业设计是要将它应用于MFC的CList控件中,所以我做了一些修改:

1、添加了一个函数

int CShowAllProcessDlg::GetCpusage(int Index, DWORD id)

用来计算每个进程的CPU利用率。第一个参数是进程在进程数组中的位置,而第二个参数是进程的ID。
重要的是,计算的公式需要获得一定时间间隔的两组进程数据来完成(这样计算才精确)。

2、定义了两个数组

__int64 LastTotalProcessCPUUsage[50];
__int64 LastCurrentProcessCPUUsage[50];
来存放获取的数据,这两个数组很重要,当然你也可以通过其他的方法实现。若要实时刷新进程的CPU利用率的话,下次运算的时候还要用到数组中的数据。

具体实现是:

int CShowAllProcessDlg::GetCpusage(int Index, DWORD id)//get CPU Usage of every Process.
{                //Index CPUUsage array.
 int cpuusage;
 PVOID pProcInfo = NULL;
 DWORD dwInfoSize = 0x20000;
 PPROCESSINFO pProcessInfo;
 DWORD dwWorkingSet;
 long ( __stdcall *NtQuerySystemInformation )( DWORD, PVOID, DWORD, DWORD );


 int CurrentDelta;
 int TotalDelta;

 __int64 TotalProcessCPUUsage = 0;
 __int64 CurrentProcessCPUUsage = 0;

/////////////////////////////////

 pProcInfo = (PVOID)(new byte[dwInfoSize]);

 NtQuerySystemInformation = (long(__stdcall*)(DWORD,PVOID,DWORD,DWORD))
 GetProcAddress( GetModuleHandle( "ntdll.dll" ),"NtQuerySystemInformation" );

 NtQuerySystemInformation(5,pProcInfo,dwInfoSize,0);

 pProcessInfo = (PPROCESSINFO)pProcInfo;

 do
 {
  TotalProcessCPUUsage += (__int64)pProcessInfo->KernelTime.QuadPart + (__int64)pProcessInfo->UserTime.QuadPart;

  if(pProcessInfo->dwProcessID == id)
  {
   dwWorkingSet = pProcessInfo->dwWorkingSet;
   CurrentProcessCPUUsage += (__int64)pProcessInfo->KernelTime.QuadPart + (__int64)pProcessInfo->UserTime.QuadPart;
  }

/////////
  if(pProcessInfo->dwOffset == 0)
  {
   break;
  }

  pProcessInfo = (PPROCESSINFO)((byte*)pProcessInfo + pProcessInfo->dwOffset);
 }while(true);

 TotalDelta = TotalProcessCPUUsage - LastTotalProcessCPUUsage[Index];
 CurrentDelta = CurrentProcessCPUUsage - LastCurrentProcessCPUUsage[Index];

 if(TotalDelta != 0)
  cpuusage = 100 * CurrentDelta / TotalDelta;

// Refresh the CPUUsage array for next caculating.
 LastTotalProcessCPUUsage[Index] = TotalProcessCPUUsage;
 LastCurrentProcessCPUUsage[Index] = CurrentProcessCPUUsage;

 delete[] pProcInfo;
 return cpuusage;

}

这两段代码我已经编译运行(Windows XP,VC 6.0)过了,基本上没有问题。

如果想要全部源代码话,请留下邮箱,欢迎讨论。

评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值