大家好,今天我来说一下显示每个进程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)过了,基本上没有问题。
如果想要全部源代码话,请留下邮箱,欢迎讨论。