代码改变世界

CPU占用率

2008-11-08 08:49  ubunoon  阅读(3021)  评论(3编辑  收藏  举报
下面是头文件
/************************************************************************/
/* 
* 作者:cpp
* 日期:2008-09-05
* 内容:提供了一个CSystemInformation类,该类可以获取CPU厂家,
*                CPU频率,CPU个数,当前使用的CPU,系统运行时占用的
*                CPU比率,系统运行的Idle时间,User时间以及Kernel时间
*                获取某个进程的句柄个数,获取随机数(比编译器自带更灵活),
*                以及将长整数(long long )转换为浮点数,宽字节与窄字节之间的互换
*
* 注意:有几个函数仅可以用在windows xp系统上,在其他系统上将失效或不起作用
*                因此,调用时需要注意,另外,如果转入到其他编译器_WIN32_WINNT用来
*                指示需要windows xp系统
*/

/************************************************************************/

#pragma once

#include
<sstream>
#include 
<cassert>

#ifndef _WINBASE_
#include 
<WinBase.h>
#endif // _WINBASE_H

//#define  _WIN32_WINNT // 该值已经在stdafx.h中被声明过,只能够用在winxp系统上

typedef 
struct _SYSTEM_BASIC_INFORMATION {
    BYTE Reserved1[
24];
    PVOID Reserved2[
4];
    CCHAR NumberOfProcessors;
}
 SYSTEM_BASIC_INFORMATION;  // 结构等同于SYSTEM_INFO

typedef 
struct
{
    
long long             IdleTime;
    DWORD           dwReversed[
76];
}
 SYSTEM_PERFORMANCE_INFORMATION;

typedef 
struct _SYSTEM_PROCESS_INFORMATION {
    ULONG NextEntryOffset;
    BYTE Reserved1[
52];
    PVOID Reserved2[
3];
    HANDLE UniqueProcessId;
    PVOID Reserved3;
    ULONG HandleCount;
    BYTE Reserved4[
4];
    PVOID Reserved5[
11];
    SIZE_T PeakPagefileUsage;
    SIZE_T PrivatePageCount;
    LARGE_INTEGER Reserved6[
6];
}
 SYSTEM_PROCESS_INFORMATION;

typedef 
struct
{
    LARGE_INTEGER liKeBootTime;
    LARGE_INTEGER liKeSystemTime;
    LARGE_INTEGER liExpTimeZoneBias;
    ULONG         uCurrentTimeZoneId;
    DWORD         dwReserved;
}
 SYSTEM_TIME_INFORMATION;  // 等同于GetSystemTimes获取到的三个数据

class CSystemInformation
{
public:
// 定义基础数据类型
    typedef std::basic_string<TCHAR> string;
    typedef std::basic_stringstream
<TCHAR> stringstream;
    typedef std::basic_string
<BYTE>  byteString;

public:
    
enum SYSTEM_INFORMATION
    
{
        SystemBasicInformation 
= 0,
        SystemPerformanceInformation 
= 2,
        SystemTimeInformation  
= 3,
    }
;
protected:
    typedef DWORD (WINAPI
* NTQUERYSYSTEMINFOMATION) (         
        SYSTEM_INFORMATION SystemInformationClass,
        PVOID SystemInformation,
        ULONG SystemInformationLength,
        PULONG ReturnLength );

public:
    CSystemInformation(
void);
public:
    
~CSystemInformation(void);
public:
    
// 获取基础信息系统,并返回处理
    const LPSYSTEM_INFO GetSystemInfo(void);

protected:
    
// 处理错误消息
    void ProcessErrorMessage(TCHAR* ErrorText);
public:
    
// 产生给定长度的随机数,由windows系统产生,比C编译器产生的更加随机
    byteString GenRandom(int len);

public:
    
// 返回转换后的wchar_t指针,并返回长度
    wchar_t* ToChar(const char* str, int* len);
public:
    
// 返回转换后的char指针,并返回长度
    char* ToChar(const wchar_t* str, int* len);
public:
    
// 获取本地机器的CPU硬件信息
    string GetCPUCompany(void);
public:
    
// 获取CPU个数
    int GetCPUNumbers(void);
public:
    
// 获取当前CPU编号-即当前使用的是哪个CPU
    int GetCurrentCPU(void);
public:
    
// 获取某个打开进程的句柄个数
    long GetProcessHandleCount(HANDLE hProcess);
public:
    
// 获取系统空闲时间
    LPFILETIME GetIdleTime(void);

public:
    
// 获取系统核心运行时间
    LPFILETIME GetKernelTime(void);
    
// 获取用户运行时间
    LPFILETIME GetUserTime(void);
public:
    
// 获取系统(空闲,核心以及用户)运行时间
    void GetSystemTimes(LPFILETIME IdleTime, LPFILETIME KernelTime, LPFILETIME UserTime,  bool ImmediateRet=false);
public:
    
// 获取CPU占用率
    double GetCPURate(void);
public:
    
// 将64位的长整数转换为64位的实数
    double LongInt2Double(LARGE_INTEGER want);
public:
    
double LongInt2Double(long long want)
    
{
        LARGE_INTEGER _want;
        memcpy( 
&_want, &want, sizeof(LARGE_INTEGER) );
        
return LongInt2Double(  _want );
    }

    
double LongInt2Double(FILETIME want)
    
{        
        LARGE_INTEGER _want;
        memcpy( 
&_want, &want, sizeof(LARGE_INTEGER) );
        
return LongInt2Double( _want);
    }

public:
    
// 获取CPU的频率,高字节部分为主频,低字节部分为次频,以GHz为单位
    int GetCPUFrenquence(void);
public:
    
// 获取当前使用的CPU编号
    int GetCurrentUseCPU(void);

public:
    
// 获取注册表所能够达到的最大尺寸,以字节为单位
    long GetMaxRegisterSize(void);
public:
    
// 获取当前注册表的尺寸,以字节为单位
    long GetCurrRegisterSize(void);

private:
    
long long  m_IdleTime;
    
long long m_KernelTime;
    
long long  m_UserTime;
    
// 用来表示是否已经获取了系统的信息,true为已经获取,false为没有获取
    bool m_bHasSystemInfo;
    wchar_t    
*m_pWChar;
    
char    *m_pchar;
private:
    
// 系统信息
    SYSTEM_INFO m_system_info;
private:
    
// NTDLL.DLL 句柄
    HMODULE m_hNtDll;
    
// NtQuerySystemInformation 函数地址
    NTQUERYSYSTEMINFOMATION NtQuerySystemInformation; 
}
;
下面是实现文件:
 
/************************************************************************/
/* 
* 作者:cpp
* 日期:2008-09-05
* 内容:提供了一个CSystemInformation类,该类可以获取CPU厂家,
*                CPU频率,CPU个数,当前使用的CPU,系统运行时占用的
*                CPU比率,系统运行的Idle时间,User时间以及Kernel时间
*                获取某个进程的句柄个数,获取随机数(比编译器自带更灵活),
*                将长整数(long long )转换为浮点数,宽字节与窄字节之间的互换
*                注册表最大容量,当前注册表容量
*/

/************************************************************************/

//#include "stdafx.h"
#include <windows.h>
#include 
"SystemInformation.h"
#include 
<WinCrypt.h>
#include 
<winbase.h>

CSystemInformation::CSystemInformation()
: m_bHasSystemInfo(
false)
{
    m_pWChar 
= NULL;
    m_pchar 
= NULL;
    m_hNtDll 
= NULL;

    m_bHasSystemInfo 
= false;

    ::memset( 
&m_system_info, 0sizeof(m_system_info));

    m_hNtDll 
= ::LoadLibrary(TEXT("ntdll.dll"));
    
if( NULL == m_hNtDll)
    
{
        
this->ProcessErrorMessage(TEXT("没有载入ntdll.dll文件!"));
        
return ;
    }

    
this->NtQuerySystemInformation = (NTQUERYSYSTEMINFOMATION) GetProcAddress(
            m_hNtDll, 
"NtQuerySystemInformation"
        );
    
if( NULL== NtQuerySystemInformation )
    
{
        
this->ProcessErrorMessage(TEXT("没有找到NtQuerySystemInformation地址!"));
        
return ;
    }

    
}


CSystemInformation::
~CSystemInformation()
{
    
if( NULL != m_pWChar)
    
{
        delete []m_pWChar;
        m_pWChar 
= NULL;
    }


    
if( NULL != m_pchar )
    
{
        delete []m_pchar;
        m_pchar 
= NULL;
    }

    
    
if( NULL != m_hNtDll )
    
{
        FreeLibrary(m_hNtDll);
        m_hNtDll 
= NULL;
    }


}


void CSystemInformation::ProcessErrorMessage( TCHAR* ErrorText )
{
    LPVOID lpMsgBuf;

    FormatMessage( 
        FORMAT_MESSAGE_ALLOCATE_BUFFER 
| FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        GetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
// Default language
        (LPTSTR) &lpMsgBuf,
        
0,
        NULL 
        );
    stringstream ss;
    ss 
<< TEXT("警告:"<< ErrorText << TEXT("存在下面的错误:\n")
        
<< lpMsgBuf << std::endl;
    MessageBox(NULL, ss.str().c_str(), TEXT(
"程序错误"), MB_ICONSTOP);
    LocalFree(lpMsgBuf);
}


const LPSYSTEM_INFO CSystemInformation::GetSystemInfo( void )
{
    ::GetSystemInfo( 
&m_system_info );
    m_bHasSystemInfo 
= true;
    
return &m_system_info;
}


CSystemInformation::byteString CSystemInformation::GenRandom( 
int len )
{
    HCRYPTPROV hCryptProc;
    TCHAR
*     UserName = TEXT("MyKeyContainer");
    
if! CryptAcquireContext(&hCryptProc, UserName, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET ) )
    
{
        ProcessErrorMessage(TEXT(
"没有得到加密锁!"));
        
return byteString();
    }


    byteString bstr;
    
try
    
{
        BYTE 
*pbBuffer = new BYTE[len];
        
if!CryptGenRandom( hCryptProc, len, pbBuffer) )
        
{
            ProcessErrorMessage(TEXT(
"没有产生得到随机数!"));
        }

        bstr 
= pbBuffer;
    }
catch()
    
{
        ProcessErrorMessage(TEXT(
"GenRandom--没有足够内存!"));
    }

    CryptReleaseContext(hCryptProc,
0);
    
return bstr;
}


wchar_t
* CSystemInformation::ToChar( const char* str, int* len )
{
    
int strLen = strlen(str);
    
try
    
{
        
if ( NULL != m_pWChar)
        
{
            
ifsizeof(m_pWChar)/sizeof(m_pWChar[0]) < strLen+1 )
            
{
                delete[] m_pWChar;
                m_pWChar 
= new wchar_t[strLen+1 ];
            }

        }
 
        
else
        
{
                m_pWChar 
= new wchar_t[strLen+1 ];
        }

        
*len = strLen + 1;
    }

    
catch()
    
{
        ProcessErrorMessage(TEXT(
"没有足够内存!"));
        
*len = 0;
    }

    
return m_pWChar;
}


char* CSystemInformation::ToChar( const wchar_t* str, int* len )
{
    
int wStrLen = ::wcslen(str);
    
try
    
{
        
if ( sizeof(m_pchar)/sizeof(m_pchar[0]) < wStrLen+1 )
        
{
            delete [] m_pchar;
            m_pchar 
= new char [ wStrLen+1];
        }
 
        
else
        
{
            m_pchar 
= new char [ wStrLen+1];
        }

        
*len = wStrLen;        
    }

    
catch()
    
{
        ProcessErrorMessage(TEXT(
"没有足够内存!"));
        
*len = 0;
    }


    
return m_pchar;
}

// 获取本地机器的CPU类型
CSystemInformation::string CSystemInformation::GetCPUCompany( void )
{
    
if! m_bHasSystemInfo )
        
this->GetSystemInfo();

    WORD processor 
= HIWORD( m_system_info.dwOemId );

    stringstream ss;
    
switch ( processor )
    
{
    
case PROCESSOR_ARCHITECTURE_INTEL:
        ss 
<< TEXT("Intel CPU")   ; 
            
break;
    
case PROCESSOR_ARCHITECTURE_AMD64:
            ss 
<<TEXT("Amd64 CPU") ;
            
break;
    
case PROCESSOR_ARCHITECTURE_ARM:
            ss 
<<TEXT("Arm CPU")  ;            
            
break;
    
case PROCESSOR_ARCHITECTURE_ALPHA:
            ss 
<<TEXT("Alpha CPU") ;        
            
break;
    
case PROCESSOR_ARCHITECTURE_IA64:
            ss 
<<TEXT("IA64 CPU") ;
            
break;
    
default:
            ss 
<<  TEXT("unknown CPU") ;
            
break;
    }

    
return ss.str();
}


// 获取CPU个数
int CSystemInformation::GetCPUNumbers(void)
{
    
if!m_bHasSystemInfo )
        
this->GetSystemInfo();

    
return m_system_info.dwNumberOfProcessors;
}


// 获取当前CPU编号-即当前使用的是哪个CPU
// 系统最多支持32个CPU
int CSystemInformation::GetCurrentCPU(void)
{
    
if!m_bHasSystemInfo )
        
this->GetSystemInfo();

    
int current_cpu = 1;
    
for(int i=0; i< 32; i++)
    
{
        
if( m_system_info.dwActiveProcessorMask & ( 1<<i) )
        
{
            current_cpu 
= i;
            
break;
        }

    }

    
return current_cpu+1;
}


// 获取某个打开进程的句柄个数
long CSystemInformation::GetProcessHandleCount(HANDLE hProcess)
{
    DWORD dwProcessCount 
= 0;

/*    if( !::GetProcessHandleCount(hProcess,&dwProcessCount) )
    {
        ProcessErrorMessage(TEXT("获取进程内句柄个数失败!"));
        dwProcessCount = 0;
    }
*/

    
return dwProcessCount;
}


// 获取系统空闲时间
LPFILETIME CSystemInformation::GetIdleTime(void)
{
/*
    if( !::GetSystemTimes((LPFILETIME)&m_IdleTime,(LPFILETIME) &m_KernelTime, (LPFILETIME)&m_UserTime))
    {
            ProcessErrorMessage(TEXT("获取系统运行时间错误!"));
    }
*/

    
return (LPFILETIME)&m_IdleTime;
}


// 获取系统核心运行时间
LPFILETIME CSystemInformation::GetKernelTime(void)
{
/*
    if(! ::GetSystemTimes((LPFILETIME)&m_IdleTime,(LPFILETIME) &m_KernelTime, (LPFILETIME)&m_UserTime))
    {
            ProcessErrorMessage(TEXT("获取系统运行时间错误!"));
    }
*/

    
return (LPFILETIME)&m_KernelTime;
}


// 获取用户运行时间
LPFILETIME CSystemInformation::GetUserTime(void)
{
  
/*
    if( ! ::GetSystemTimes((LPFILETIME)&m_IdleTime, (LPFILETIME)&m_KernelTime, (LPFILETIME)&m_UserTime) )
    {
            ProcessErrorMessage(TEXT("获取系统运行时间错误!"));
    }
  
*/

    
return (LPFILETIME)&m_UserTime;
}



// 同时获取获取系统(空闲,核心以及用户)运行时间
void CSystemInformation::GetSystemTimes(LPFILETIME IdleTime, LPFILETIME KernelTime, LPFILETIME UserTime, bool ImmediateRet /*=false*/)
{
/*
    if( ! ::GetSystemTimes( IdleTime, KernelTime, UserTime) )
    {
            ProcessErrorMessage(TEXT("获取系统运行时间错误!"));
    }
*/

    
if( ImmediateRet )
        
return ;

    memcpy( 
&m_IdleTime, IdleTime, sizeof( FILETIME) );
    memcpy( 
&m_KernelTime, KernelTime, sizeof( FILETIME) );
    memcpy( 
&m_UserTime, UserTime, sizeof(FILETIME) );

}


// 获取CPU占用率
double CSystemInformation::GetCPURate(void)
{
    SYSTEM_PERFORMANCE_INFORMATION  SysPerfInfo;
    SYSTEM_TIME_INFORMATION        SysTimeInfo;
    SYSTEM_BASIC_INFORMATION       SysBaseInfo;

    
double IdleTime = 0 ;
    
static double OldIdleTime = 0;   
    
double SystemTime = 0;
    
static double OldSystemTime = 0;

    
if( NtQuerySystemInformation )
    
{
        DWORD status 
= NtQuerySystemInformation(SystemBasicInformation, &SysBaseInfo, 
                
sizeof(SYSTEM_BASIC_INFORMATION), NULL);
        
//GetSystemInfo();

        
if ( NO_ERROR != status)
        
{
            ProcessErrorMessage(TEXT(
"没有获取到系统基础信息!"));
            
return 0;
        }


        
//GetIdleTime();    // 获取系统的三个时间
        status = NtQuerySystemInformation(SystemTimeInformation, &SysTimeInfo,
        
sizeof(SYSTEM_TIME_INFORMATION), NULL);
        
if ( NO_ERROR != status)
        
{
            ProcessErrorMessage(TEXT(
"没有获取到系统基础信息!"));
            
return 0;
        }


        status 
= NtQuerySystemInformation(SystemPerformanceInformation, &SysPerfInfo, 
                        
sizeof(SYSTEM_PERFORMANCE_INFORMATION), NULL);
        
if ( NO_ERROR != status)
        
{
                ProcessErrorMessage(TEXT(
"没有获取到系统基础信息!"));
                
return 0;
        }


        
if ( 0 != OldIdleTime )
        
{
            IdleTime 
= LongInt2Double(SysPerfInfo.IdleTime)  - OldIdleTime;
            SystemTime 
= LongInt2Double(SysTimeInfo.liKeSystemTime) - OldSystemTime;
            
// 采用这种方式获取的CPU占用率,获取的值与任务管理相差较大
            
//SystemTime = LongInt2Double(m_KernelTime) - OldSystemTime; 
            IdleTime = IdleTime/SystemTime;
            
            IdleTime 
= 100 -  IdleTime*100.0/(double)SysBaseInfo.NumberOfProcessors;
        }

        OldIdleTime 
= LongInt2Double(SysPerfInfo.IdleTime);
        OldSystemTime 
=LongInt2Double( SysTimeInfo.liKeSystemTime );
        
//OldSystemTime = LongInt2Double(m_KernelTime);
        
//Sleep(100);
    }

    
return IdleTime;
}


// 将64位的长整数转换为64位的实数
double CSystemInformation::LongInt2Double(LARGE_INTEGER want)
{
    
return ((double)(want.HighPart) * 4.294967296E9 + (double)(want.LowPart) );
}



// 获取CPU的频率,高word部分为主频,低word部分为次频,以GHz为单位
int CSystemInformation::GetCPUFrenquence(void)
{
    
if ( !m_bHasSystemInfo )
    
{
        
this->GetSystemInfo();
    }

/************************************************************************
#ifdef _DEBUG
    stringstream ss;
    ss << HIBYTE(m_system_info.wProcessorRevision) <<LOBYTE(m_system_info.wProcessorRevision) << std::endl;
    AfxMessageBox( ss.str().c_str() );
#endif // _DEBUG
*/

    
return m_system_info.wProcessorRevision;
}


// 获取注册表所能够达到的最大尺寸,以字节为单位
long CSystemInformation::GetMaxRegisterSize(void)
{
    unsigned 
long Max = 0;
    unsigned 
long Curr = 0;
/*    if ( !GetSystemRegistryQuota(&Max, &Curr) )
    {
        ProcessErrorMessage(TEXT("没有获取到系统的注册表存储容量信息!"));
        return 0;
    }
*/

    
return Max;
}


// 获取当前注册表的尺寸,以字节为单位
long CSystemInformation::GetCurrRegisterSize(void)
{
    unsigned 
long Max = 0;
    unsigned 
long Curr = 0;
/*
    if ( !GetSystemRegistryQuota(&Max, &Curr) )
    {
        ProcessErrorMessage(TEXT("没有获取到系统的注册表存储容量信息!"));
        return 0;
    }
*/

    
return Curr;    
}


需要注意的是,其中还有部分成员函数不能够良好工作,但CPU占用率已经可以非常良好的运行,与windows的任务管理器基本上没有什么大的差别,但未对百分比数据进行修订,以使得数据位数达到一致!