接下来,我们看如何获取进程的CPU使用率:
CPU使用率:指进程在一段时间内消耗的CPU时间与该时间段长度的比值。
windows本身并没有提供直接获取进程CPU使用率的函数,但我们可以根据进程的计时信息来间接计算出进程的瞬时CPU占用:
1)记录进程当前在用户模式和内核模式下已经执行的时间;
2)1s后,再次记录进程在用户模式和内核模式下已经执行的时间;
3)将两次时间相减,就是这1s时间内进程在CPU上执行的时间;用执行时间/记录间隔时间 = 进程的CPU占比
老规矩,看需要用到哪些系统API函数:
GetProcessTimes函数:
BOOL GetProcessTimes(
HANDLE hProcess,
LPFILETIME lpCreationTime,
LPFILETIME lpExitTime,
LPFILETIME lpKernelTime,
LPFILETIME lpUserTime
);
函数功能:获取指定进程的计时信息
参数:
hProcess:指定进程的句柄;
lpCreationTime:返回进程的创建时间;
lpExitTime:返回进程的退出时间,若进程尚未退出,此返回值内容不确定;
lpKernelTime:返回进程在内核模式下已执行的时间;
lpUserTime:返回进程在用户模式下已执行的时间;
返回值:函数成功返回非0,失败返回0.
需要注意的是,内核模式下和用户模式下的执行时间,是指进程的所有线程的执行时间和,如果改进程在多个CPU核上运行,则值可能会超过经过的实时时间。这点也比较好理解,如果进程支持在多核上运行,每个核上的执行时间相加,则有可能大于实时经过的时间。
GetSystemTimeAsFileTime函数:
void GetSystemTimeAsFileTime(
LPFILETIME lpSystemTimeAsFileTime
);
函数功能:检索当前系统日期和时间,这个函数返回的时间精度相对于其他的API函数高很多,以ns为单位
参数:lpSystemTimeAsFileTime:返回当前系统日期和时间
详见:https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime
GetSystemInfo函数
void GetSystemInfo(
LPSYSTEM_INFO lpSystemInfo
);
函数说明:检索当前系统的信息
参数:lpSystemInfo返回系统的信息
SYSTEM_INFO结构:https://docs.microsoft.com/zh-cn/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info
实现代码如下:
DWORD getProcessHandleCount(LPCWSTR processName)
{
DWORD dwHandleCount;
DWORD dwHandleCountAll = 0;
std::vector<HANDLE> processHandleGroup = GetProcessHandle(processName);
printf("vector size is %d.\n",processHandleGroup.size());
if(0 == processHandleGroup.size())
{
return -2;
}
std::vector<HANDLE>::iterator it;
for(it=processHandleGroup.begin();it!=processHandleGroup.end();it++)
{
GetProcessHandleCount(*it, &dwHandleCount);
CloseHandle(*it);
dwHandleCountAll += dwHandleCount;
printf ("Current Process Handle count : %d\n", dwHandleCount);
}
return dwHandleCountAll;
}
//时间转换
uint64_t get_utc_time(const FILETIME* ftime)
{
LARGE_INTEGER ti;
ti.LowPart = ftime->dwLowDateTime;
ti.HighPart = ftime->dwHighDateTime;
return ti.QuadPart;
}
//获取CPU核数
int get_processor_number()
{
SYSTEM_INFO info;
GetSystemInfo(&info);
return (int)info.dwNumberOfProcessors;
}
//获取CPU使用率
float get_cpu_usage(HANDLE hProcess, int processor)
{
FILETIME now;
FILETIME creation_time;
FILETIME exit_time;
FILETIME kernel_time;
FILETIME user_time;
int64_t system_time;
int64_t time;
int64_t system_time_delta;
int64_t time_delta;
DWORD exitcode;
int64_t last_time;
int64_t last_system_time;
float cpu;
GetSystemTimeAsFileTime(&now); //获取当前时间(高精度)
//判断进程是否已经退出
GetExitCodeProcess(hProcess, &exitcode);
if (exitcode != STILL_ACTIVE) {
printf("process had exit.\n");
return -1;
}
//计算占用CPU的百分比
if (!GetProcessTimes(hProcess, &creation_time, &exit_time, &kernel_time, &user_time))
{
printf("GetProcessTimes faild.\n");
return -1;
}
system_time = (get_utc_time(&kernel_time) + get_utc_time(&user_time))/ processor;
time = get_utc_time(&now);
last_system_time = system_time;
last_time = time;
//第二次
Sleep(1000);
//计算占用CPU的百分比
GetSystemTimeAsFileTime(&now);//获取当前时间(高精度)
if (!GetProcessTimes(hProcess, &creation_time, &exit_time, &kernel_time, &user_time))
{
printf("GetProcessTimes faild.\n");
return -1;
}
system_time = (get_utc_time(&kernel_time) + get_utc_time(&user_time))/ processor;
time = get_utc_time(&now);
system_time_delta = system_time - last_system_time;
time_delta = time - last_time;
cpu = (float)system_time_delta * 100 / (float)time_delta;
return cpu;
}
float getProcessCPUUsage(LPCWSTR processName)
{
int processor;
float cpuUsage;
float processCpuUsageAll=0;
std::vector<HANDLE> processHandleGroup = GetProcessHandle(processName);
printf("vector size is %d.\n",processHandleGroup.size());
if(0 == processHandleGroup.size())
{
return -2;
}
processor = get_processor_number();
printf("processor is %d.\n",processor);
std::vector<HANDLE>::iterator it;
for(it=processHandleGroup.begin();it!=processHandleGroup.end();it++)
{
cpuUsage = get_cpu_usage(*it,processor);
CloseHandle(*it);
if(cpuUsage < 0)
{
continue;
}
processCpuUsageAll += cpuUsage;
printf("Current Process cpu : %f \n",cpuUsage);
}
printf("Process cpu usage sum: %f \n",processCpuUsageAll);
return processCpuUsageAll;
}
结合上一篇获取的进程句柄,我们就能很方便的获取所有指定进程名的进程当前CPU占用情况。
下一篇,将介绍如何使用进程句柄获取进程当前句柄数和内存占用。
本文为作者原创,如需转载,请在评论区征得作者同意,原创链接:https://blog.csdn.net/anranjingsi/article/details/106124258