获取进程占用的CPU

由于程序需要一直运行,所以做了一个检测程序是否正常的检测程序,发现程序占用CPU过高或者为0时重启主程序。

 通常的获取CPU占有率的方法是NtQuerySystemInformation, NtQueryInformationProcess,但是由于它们不是public的,使用不方便,一个可观的替代方案是

 GetSystemTimes和GetProcessTimes。

 BOOL WINAPI GetSystemTimes(

   _Out_opt_ LPFILETIME lpIdleTime,

    _Out_opt_ LPFILETIME lpKernelTime, 

   _Out_opt_ LPFILETIME lpUserTime  );

BOOL WINAPI GetProcessTimes( 

    _In_ HANDLE hProcess,

   _Out_ LPFILETIME lpCreationTime,

    _Out_ LPFILETIME lpExitTime,

   _Out_ LPFILETIME lpKernelTime,

    _Out_ LPFILETIME lpUserTime );


GetSystemTimes获得系统(自开机以来)处于Kernel状态下面的CPU时间,以及系统处于User状态下的时间,以及Idle的时间.我们只用Kernel时间和User时间, 不用Idle时间.

相应的, GetProcess也能求出一个进程在上面3中状态下的时间.

下面公式可以求出进程的CPU占用率.

                  CpuPercentageEquation


代码如下:

/CpuUsage.h

#pragma once
class CpuUsage
{
public:
    CpuUsage(DWORD dwProcessID);
    ~CpuUsage(void);

public:
    ULONGLONG GetUsageEx();
    ULONGLONG GetSystemNonIdleTimes();
    ULONGLONG GetProcessNonIdleTimes();
private:
    ULONGLONG SubtractTimes(const FILETIME &ftA,const FILETIME& ftB);
    ULONGLONG AddTimes(const FILETIME& ftA,const FILETIME& ftB);
    bool EnoughTimePassed();
    inline bool IsFirstRun() const {return (m_dwLastRun==0);}

    /system total times
    FILETIME m_ftPrevSysKernel;
    FILETIME m_ftPrevSysUser;
    
    process times
    FILETIME m_ftPrevProcKernel;
    FILETIME m_ftPrevProcUser;

    ULONGLONG m_ullPrevSysNonIdleTime;这个变量和后面的变量记录上次获得的非
                                                                   idle的系统cpu时间和进程时间
    ULONGLONG m_ullPrevProcNonIdleTime;/这个类只绑定一个进程,在构造函数里面初始化
    ULONGLONG m_nCpuUsage;
    ULONGLONG m_dwLastRun;
    DWORD m_dwProcessID;
    HANDLE m_hProcess;
    volatile LONG m_lRunCount;
};



//CpuUsage.cpp

#include "StdAfx.h"
#include "CpuUsage.h"
#include <strsafe.h>


void ErrorMsg(LPTSTR lpszFunction);
BOOL SetPrivilege(HANDLE hProcess,LPCTSTR lpszPrivilege,BOOL bEnablePrivilege);

#ifdef  USE_DEPRECATED_FUNCS
#define SystemBasicInformation                    0
 #define SystemPerformanceInformation            2
 #define SystemTimeInformation                    3
 #define SystemProcessorPerformanceInformation    8
 #define ProcessTimes                            4
 
#define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))

typedef struct
{
    DWORD dwUnknown1;
    ULONG uKeMaximumIncrement;
    ULONG uPageSize;
    ULONG uMmNumberOfPhysicalPages;
    ULONG uMmLowestPhysicalPage;
    ULONG uMmHighestPhysicalPage;
    ULONG uAllocationGranularity;
    PVOID pLowestUserAddress;
    PVOID pMmHighestUserAddress;
    ULONG uKeActiveProcessors;
    BYTE bKeNumberProcessors;
    BYTE bUnknown2;
    WORD wUnknown3;
} SYSTEM_BASIC_INFORMATION;

typedef struct
{
    LARGE_INTEGER liIdleTime;
    DWORD dwSpare[312];
} SYSTEM_PERFORMANCE_INFORMATION;

typedef struct
{
    LARGE_INTEGER liKeBootTime;
    LARGE_INTEGER liKeSystemTime;
    LARGE_INTEGER liExpTimeZoneBias;
    ULONG uCurrentTimeZoneId;
    DWORD dwReserved;
} SYSTEMTEXTIME_INFORMATION;

typedef struct
    _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
{
    LARGE_INTEGER IdleTime;
    LARGE_INTEGER KernelTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER Reserved1[2];
    ULONG Reserved2;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;

typedef struct _KERNEL_USERTEXTIMES
{
    LARGE_INTEGER CreateTime;
    LARGE_INTEGER ExitTime;
    LARGE_INTEGER KernelTime;
    LARGE_INTEGER UserTime;
} KERNEL_USERTEXTIMES, *PKERNEL_USERTEXTIMES;

typedef LONG (WINAPI *PROCNTQSI)(UINT, PVOID, ULONG, PULONG);
PROCNTQSI NtQuerySystemInformation;

typedef LONG (WINAPI *PROCNTQIP)(HANDLE, UINT, PVOID, ULONG, PULONG);
PROCNTQIP NtQueryInformationProcess;

ULONGLONG CpuUsage::GetSystemNonIdleTimes()
{
    SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo;
    SYSTEMTEXTIME_INFORMATION SysTimeInfo;
    SYSTEM_BASIC_INFORMATION SysBaseInfo;
    SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SysProcPerfInfo[32];
    LONG status;
    NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "NtQuerySystemInformation");
    if (!NtQuerySystemInformation)
        return 0;
    status = NtQuerySystemInformation(SystemBasicInformation, &SysBaseInfo, sizeof(SysBaseInfo), NULL);
    if (status != NO_ERROR)
    {
        MessageBox(TEXT("FailSystemInfo"));
        return 0;
    }
    status = NtQuerySystemInformation(SystemProcessorPerformanceInformation, SysProcPerfInfo, sizeof(SysProcPerfInfo), NULL);
    if(status != NO_ERROR) return 0;
    int nProcessors = SysBaseInfo.bKeNumberProcessors; //机器内部CPU的个数
    ULONGLONG ullSysTotal = 0;
    for(int i = 0; i < nProcessors; i++)
    {
        ullSysTotal += SysProcPerfInfo[i].KernelTime.QuadPart + SysProcPerfInfo[i].UserTime.QuadPart;
    }
    return ullSysTotal;
}

ULONGLONG CpuUsage::GetProcessNonIdleTimes()
{
    KERNEL_USERTEXTIMES KernelUserTimes;
    ::ZeroMemory(&KernelUserTimes, sizeof(KernelUserTimes));
    NtQueryInformationProcess = (PROCNTQIP)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "NtQueryInformationProcess");
    LONG status = NtQueryInformationProcess(m_hProcess, ProcessTimes, &KernelUserTimes, sizeof(KernelUserTimes), NULL);
    if(status == 0)
    {
        ErrorExit(TEXT("GetProcessNonIdleTimes"));
        return 0;
    }
    return KernelUserTimes.KernelTime.QuadPart + KernelUserTimes.UserTime.QuadPart;

}
#endif
CpuUsage::CpuUsage(DWORD dwProcessID):m_nCpuUsage(0),
    m_dwLastRun(0),
    m_lRunCount(0),
    m_dwProcessID(dwProcessID),
    m_ullPrevProcNonIdleTime(0),
    m_ullPrevSysNonIdleTime(0)
{
    HANDLE hProcess = GetCurrentProcess();
    SetPrivilege(hProcess,SE_DEBUG_NAME,TRUE);
    m_hProcess=::OpenProcess(PROCESS_QUERY_INFORMATION,TRUE,m_dwProcessID);
    if (m_hProcess==NULL)
    {
        ErrorMsg(TEXT("OpenProcess Fail"));
    }
    ZeroMemory(&m_ftPrevSysKernel, sizeof(FILETIME));
    ZeroMemory(&m_ftPrevSysUser, sizeof(FILETIME));
    ZeroMemory(&m_ftPrevProcKernel, sizeof(FILETIME));
    ZeroMemory(&m_ftPrevProcUser, sizeof(FILETIME));
}


CpuUsage::~CpuUsage(void)
{

}

ULONGLONG CpuUsage::SubtractTimes(const FILETIME &ftA, const FILETIME &ftB)
{
    LARGE_INTEGER a, b;
    a.LowPart = ftA.dwLowDateTime;
    a.HighPart = ftA.dwHighDateTime;
    b.LowPart = ftB.dwLowDateTime;
    b.HighPart = ftB.dwHighDateTime;
    return a.QuadPart - b.QuadPart;
}

ULONGLONG CpuUsage::AddTimes(const FILETIME &ftA, const FILETIME &ftB)
{
    LARGE_INTEGER a, b;
    a.LowPart = ftA.dwLowDateTime;
    a.HighPart = ftA.dwHighDateTime;

    b.LowPart = ftB.dwLowDateTime;
    b.HighPart = ftB.dwHighDateTime;

    return a.QuadPart + b.QuadPart;
}

bool CpuUsage::EnoughTimePassed()
 {
     const int minElapsedMS = 250;//milliseconds
     ULONGLONG dwCurrentTickCount = GetTickCount();
     return (dwCurrentTickCount - m_dwLastRun) > minElapsedMS;
 }

#ifndef  USE_DEPRECATED_FUNCS

ULONGLONG CpuUsage::GetSystemNonIdleTimes()
{
    FILETIME ftSysIdle, ftSysKernel, ftSysUser;
    if(!GetSystemTimes(&ftSysIdle, &ftSysKernel, &ftSysUser))
    {
        ErrorMsg(TEXT("GetSystemTimes"));
        return 0;
    }
    return AddTimes(ftSysKernel, ftSysUser);
}

ULONGLONG CpuUsage::GetProcessNonIdleTimes()
{
    FILETIME ftProcCreation, ftProcExit, ftProcKernel, ftProcUser;
    if(!GetProcessTimes(m_hProcess, &ftProcCreation, &ftProcExit, &ftProcKernel, &ftProcUser) && false)
    {
        ErrorMsg(TEXT("GetProcessNonIdleTimes"));
        return 0;
    }
    return AddTimes(ftProcKernel, ftProcUser);
}
#endif

ULONGLONG CpuUsage::GetUsageEx()
{
    ULONGLONG nCpuCopy = m_nCpuUsage;
    if (::InterlockedIncrement(&m_lRunCount) == 1)
    {
        if (!EnoughTimePassed())
        {
            ::InterlockedDecrement(&m_lRunCount);
            return nCpuCopy;
        }
        ULONGLONG ullSysNonIdleTime = GetSystemNonIdleTimes();
        ULONGLONG ullProcNonIdleTime = GetProcessNonIdleTimes();
        if (!IsFirstRun())
        {
            ULONGLONG ullTotalSys = ullSysNonIdleTime - m_ullPrevSysNonIdleTime;
            if(ullTotalSys == 0)
            {
                ::InterlockedDecrement(&m_lRunCount);
                return nCpuCopy;
            }
            m_nCpuUsage = ULONGLONG((ullProcNonIdleTime - m_ullPrevProcNonIdleTime) * 100.0 / (ullTotalSys));
            m_ullPrevSysNonIdleTime = ullSysNonIdleTime;
            m_ullPrevProcNonIdleTime = ullProcNonIdleTime;
        }
        m_dwLastRun = (ULONGLONG)GetTickCount();
        nCpuCopy = m_nCpuUsage;
    }
    ::InterlockedDecrement(&m_lRunCount);
    return nCpuCopy;
}


BOOL SetPrivilege(HANDLE hProcess, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
    HANDLE hToken;
    if(!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken))
    {
        ErrorMsg(TEXT("OpenProcessToken"));
        return FALSE;
    }
    LUID luid;
    if(!LookupPrivilegeValue(NULL, lpszPrivilege, &luid))
    {
        ErrorMsg(TEXT("LookupPrivilegeValue"));
        return FALSE;
    }
    TOKEN_PRIVILEGES tkp;
    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = luid;
    tkp.Privileges[0].Attributes = (bEnablePrivilege) ? SE_PRIVILEGE_ENABLED : FALSE;
    if(!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL))
    {
        ErrorMsg(TEXT("AdjustTokenPrivileges"));
        return FALSE;
    }
    return TRUE;
}


void ErrorMsg(LPTSTR lpszFunction)
{
    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        LANG_USER_DEFAULT,
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    // Display the error message

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
        (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
    StringCchPrintf((LPTSTR)lpDisplayBuf,
        LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("%s failed with error %d: %s"),
        lpszFunction, dw, lpMsgBuf);
    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
    ExitProcess(dw);
}


/测试函数

    DWORD dwProcId =9840;
    CpuUsage cu(dwProcId);
    SYSTEMTIME st;
    while(true)
    {
        GetLocalTime(&st);
        char Msg[MAX_PATH]={0};
        sprintf(Msg,"Process(pid:%d) uses %I64d%% cpu at %02d:%02d.%02d\n", dwProcId, cu.GetUsageEx(), st.wHour, st.wMinute, st.wSecond);
        MessageBoxA(NULL,Msg,"msg",0);
        ::Sleep(second);
    }

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值