如何监控windows进程的句柄、内存和cpu(二)

接下来,我们看如何获取进程的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.

详见:https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocesstimes

需要注意的是,内核模式下和用户模式下的执行时间,是指进程的所有线程的执行时间和,如果改进程在多个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

原创文章 5 获赞 5 访问量 454

猜你喜欢

转载自blog.csdn.net/anranjingsi/article/details/106124258