添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Introduction

Since a very long time, a lot of people wanted to get the CPU usage from the computer.

You've a lot of ways to do this like calling registry like key or PerfCounter . But TaskManager doesn't call any of these ... If you're looking from the import table of TaskManager , you can find:

ntdll.dll Import Adress Table: 0x00001414 Import Name Table: 0x00013C2C 0x7C90E213 260 NtQueryVirtualMemory 0x7C90DDF9 209 NtOpenThread 0x7C90D586 103 NtClose 0x7C90E1AA 255 NtQuerySystemInformation

So there is no other solution to have this information to dig into undocumented NtQuerySystemInformation . With this nice warning at the beginning of the article: [ NtQuerySystemInformation is available for use in Windows 2000 and Windows XP. It may be altered or unavailable in subsequent versions. Applications should use the alternate functions listed in this topic.]

No other solution?

Well, GetSystemTimes is a good function if you have the requirements:

Client Requires Windows XP SP1. Server Requires Windows Server 2003 . Header Declared in Winbase.h; include Windows.h. Library Link to Kernel32.lib. DLL Requires Kernel32.dll.

How to Use It?

Call this:

FILETIME idleTime; FILETIME kernelTime; FILETIME userTime; BOOL res = GetSystemTimes( &idleTime, &kernelTime, &userTime );

and voilà, you have almost what you need.

Now you have to poll this function and make a little calculus.

usr = userTime - last_userTime; ker = kernelTime - last_kernelTime; idl = idleTime - last_idleTime;

System time is:

sys = kerl + usr

idleTime is the rest because "System Idle" process is taking 100 % of CPU.

So CPU is:

cpu = int ( (sys - idl) *100 / sys );

Conclusion

It was a very long wait before Microsoft gave us this function. Now it's done but there is still one problem. For multiple processor system, you don't have the right information.

In the sample, you can find the use of GetSystemTimes and GetProcessTimes and a little class to do everything.

class CPU public : CPU( void ); ~CPU( void ); // return : // % of cpu usage for this process // % cpu systemUsage // uptime for this process int GetUsage( int* pSystemUsage, TKTime* pUpTime );

History

  • 20 th December, 2004: Initial version
  • [CPU.cpp]
    Line 052: 'if( s_hKernel == NULL )' should be 'if( s_hKernel )'
    Line 191: in case 'sys == 0 || div == 0' you should return old values (fail)
    Line 207~208: 's_index' incremented twice. suggested:
    s_cpu[s_index] = cpu; s_cpuProcess[s_index] = cpuProcess; s_index = (s_index + 1 ) % _countof(s_cpu); and better to lock whole function if you don't need any atomic field update.
    Sign In · View Thread what is the type and where have u defined last_userTime, last_kernelTime, last_idleTime, usr, ker, idl,sys in the code. sorry I couldn't compile the code. any help can be so useful. tnx
    Sign In · View Thread look in TKTime.h you've got the type definition
    -----------------------------
    ejor @ http://dev.jesover.net

    Sign In · View Thread Huummmm how could say that.....
    did you opened the zip an look at files ?
    -----------------------------
    ejor @ http://dev.jesover.net

    Sign In · View Thread tnx. i download the rar and i could run it. could u please tell me what is in the process and system variable? and how can i get total cpu usage in percent? i want to get when is system in ideal time(for example it is 10 min that cpu usage is less than 5 %). tnx a lot
    Sign In · View Thread Question When I use this function, I encountered an error that this function is undeclared, do you know why? Pin
    love_fairytale 13-Mar-12 22:12
    love_fairytale 13-Mar-12 22:12 Hey ejor:
    I want to ask you a question.
    When I use this function, I encountered an error that this function is undeclared.
    I'm sure I have included the windows.h and according to the introduction of MSDN, defined the _WIN32_WINNT as 0x0501, but the error is still existent. Confused | :confused:
    Can you give me some help to solve it?
    Thank you very much~ Smile | :)
    Sign In · View Thread Answer Re: When I use this function, I encountered an error that this function is undeclared, do you know why? Pin
    ejor 20-Mar-12 3:13
    ejor 20-Mar-12 3:13 Hi Ejor
    Could you please let me know how to get the CPU Usage in % of a particular running process say 'taskmgr.exe'?
    I would like to get the CPU Usage of a particular process running in PC.
    Please help me. Cry | :((
    Thanks
    Sanjib
    Sign In · View Thread Here's the code that I got after throwing away about 90% of junk from your code.
    This code allows getting CPU usage, and works not only on Windows XPSP1 or later, but also on Windows 2000/XP/2003/Vista/2008.
    I did this to include CPU usage into ProSysLib as one of the CPU parameters.
    Just two files, header + cpp.
    ProcessorUsage.h:
    class CProcessorUsage typedef BOOL (WINAPI * pfnGetSystemTimes)(LPFILETIME lpIdleTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime ); typedef LONG (WINAPI * pfnNtQuerySystemInformation)(ULONG SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); struct PROC_PERF_INFO LARGE_INTEGER IdleTime; LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER Reserved1[ 2 ]; ULONG Reserved2; public: CProcessorUsage(); ~CProcessorUsage(); USHORT GetUsage(); private: void GetSysTimes( __int64 & idleTime, __int64 & kernelTime, __int64 & userTime); /// ///////////////////////////////////////////// // Set of static variables to be accessed from // within critical section by multiple threads: static DWORD s_TickMark; static __int64 s_time; static __int64 s_idleTime; static __int64 s_kernelTime; static __int64 s_userTime; static int s_lastCpu; static int s_cpu[ 5 ]; static __int64 s_kernelTimeProcess; static __int64 s_userTimeProcess; static int s_cpuProcess[ 5 ]; static int s_count; static int s_index;
    /// ////////////////////////////////////////////// pfnGetSystemTimes s_pfnGetSystemTimes; pfnNtQuerySystemInformation s_pfnNtQuerySystemInformation; CRITICAL_SECTION m_cs; PROC_PERF_INFO * m_pInfo; ULONG m_uInfoLength; ProcessorUsage.cpp
    DWORD CProcessorUsage::s_TickMark = 0 ; __int64 CProcessorUsage::s_time = 0 ; __int64 CProcessorUsage::s_idleTime = 0 ; __int64 CProcessorUsage::s_kernelTime = 0 ; __int64 CProcessorUsage::s_userTime = 0 ; __int64 CProcessorUsage::s_kernelTimeProcess = 0 ; __int64 CProcessorUsage::s_userTimeProcess = 0 ; int CProcessorUsage::s_count = 0 ; int CProcessorUsage::s_index = 0 ; int CProcessorUsage::s_lastCpu = 0 ; int CProcessorUsage::s_cpu[ 5 ] = { 0 , 0 , 0 , 0 , 0 }; int CProcessorUsage::s_cpuProcess[ 5 ] = { 0 , 0 , 0 , 0 , 0 }; CProcessorUsage::CProcessorUsage() ::InitializeCriticalSection(&m_cs); s_pfnNtQuerySystemInformation = NULL; s_pfnGetSystemTimes = NULL; m_pInfo = NULL; m_uInfoLength = 0 ; HMODULE hModule = ::GetModuleHandle(_T( " kernel32.dll" )); if (hModule) s_pfnGetSystemTimes = (pfnGetSystemTimes)::GetProcAddress(hModule, " GetSystemTimes" ); if (!s_pfnGetSystemTimes) hModule = ::GetModuleHandle(_T( " ntdll.dll" )); if (hModule) s_pfnNtQuerySystemInformation = (pfnNtQuerySystemInformation)::GetProcAddress(hModule, " NtQuerySystemInformation" ); if (s_pfnNtQuerySystemInformation) s_pfnNtQuerySystemInformation( 8 , NULL, 0 , &m_uInfoLength); m_pInfo = new PROC_PERF_INFO[m_uInfoLength / sizeof (PROC_PERF_INFO)]; s_TickMark = ::GetTickCount(); CProcessorUsage::~CProcessorUsage() if (m_pInfo) delete m_pInfo; ::DeleteCriticalSection(&m_cs); void CProcessorUsage::GetSysTimes( __int64 & idleTime, __int64 & kernelTime, __int64 & userTime) if (s_pfnGetSystemTimes) s_pfnGetSystemTimes((LPFILETIME)&idleTime, (LPFILETIME)&kernelTime, (LPFILETIME)&userTime); idleTime = 0 ; kernelTime = 0 ; userTime = 0 ; if (s_pfnNtQuerySystemInformation && m_uInfoLength && !s_pfnNtQuerySystemInformation( 0x08 , m_pInfo, m_uInfoLength, &m_uInfoLength)) // NtQuerySystemInformation returns information for all // CPU cores in the system, so we take the average here: int nCores = m_uInfoLength / sizeof (PROC_PERF_INFO); for ( int i = 0 ;i < nCores;i ++) idleTime += m_pInfo[i].IdleTime.QuadPart; kernelTime += m_pInfo[i].KernelTime.QuadPart; userTime += m_pInfo[i].UserTime.QuadPart; idleTime /= nCores; kernelTime /= nCores; userTime /= nCores; USHORT CProcessorUsage::GetUsage() __int64 sTime; int sLastCpu; CCritSecLock cs(m_cs); sTime = s_time; sLastCpu = s_lastCpu; if (((::GetTickCount() - s_TickMark) & 0x7FFFFFFF ) < = 200 ) return sLastCpu; __int64 time; __int64 idleTime; __int64 kernelTime; __int64 userTime; __int64 kernelTimeProcess; __int64 userTimeProcess; ::GetSystemTimeAsFileTime((LPFILETIME)&time); if (!sTime) GetSysTimes(idleTime, kernelTime, userTime); FILETIME createTime; FILETIME exitTime; ::GetProcessTimes(::GetCurrentProcess(), &createTime, &exitTime, (LPFILETIME)&kernelTimeProcess, (LPFILETIME)&userTimeProcess); s_time = time; s_idleTime = idleTime; s_kernelTime = kernelTime; s_userTime = userTime; s_kernelTimeProcess = kernelTimeProcess; s_userTimeProcess = userTimeProcess; s_lastCpu = 0 ; s_TickMark = ::GetTickCount(); return 0 ; __int64 div = (time - sTime); GetSysTimes(idleTime, kernelTime, userTime); FILETIME createTime; FILETIME exitTime; ::GetProcessTimes(::GetCurrentProcess(), &createTime, &exitTime, (LPFILETIME)&kernelTimeProcess, (LPFILETIME)&userTimeProcess); int cpu; int cpuProcess; __int64 usr = userTime - s_userTime; __int64 ker = kernelTime - s_kernelTime; __int64 idl = idleTime - s_idleTime; __int64 sys = (usr + ker); if (sys) cpu = int ((sys - idl) * 100 / sys); // System Idle take 100 % of cpu; cpu = 0 ; cpuProcess = int ((((userTimeProcess - s_userTimeProcess) + (kernelTimeProcess - s_kernelTimeProcess)) * 100 ) / div); s_time = time; s_idleTime = idleTime; s_kernelTime = kernelTime; s_userTime = userTime; s_kernelTimeProcess = kernelTimeProcess; s_userTimeProcess = userTimeProcess; s_cpu[(s_index ++) %5] = cpu; s_cpuProcess[(s_index++) %5] = cpuProcess; s_count ++; if (s_count > 5 ) s_count = 5 ; cpu = 0 ; int i; for (i = 0 ; i < s_count; i++ ) cpu += s_cpu[i]; cpuProcess = 0 ; for (i = 0 ; i < s_count; i++ ) cpuProcess += s_cpuProcess[i]; cpu /= s_count; cpuProcess /= s_count; s_lastCpu = cpu; sLastCpu = s_lastCpu; s_TickMark = ::GetTickCount(); return sLastCpu;
    Professional System Library on www.prosyslib.org

    Sign In · View Thread Just don't forget a link where you find the code in your project Smile | :)
    -----------------------------
    ejor @ http://dev.jesover.net

    modified on Tuesday, September 2, 2008 2:54 PM

    Sign In · View Thread Thank you!
    And could you, please, explain me the magic of 5 that you used as dimension for two arrays in your code?
    Thank you,
    Vitaly
    Professional System Library on www.prosyslib.org

    Sign In · View Thread just an heuristic to have something similar to task manager
    You do not want to have all updates
    you want something more smooth
    Try other way if you prefer Smile | :)
    -----------------------------
    ejor @ http://dev.jesover.net

    Sign In · View Thread Got you! Smile | :) I just wanted to know, since you did not document those things.
    And if you think that the shorter code that i published above can be further simplified, please let me know, 'cos i'm still not quite sure about its logic, seems quite a bit different from what you wrote in the article itself where you just give a simple formula, and then the actual code looks way more complicated...
    Professional System Library on www.prosyslib.org

    Sign In · View Thread I've documented the important part of the algo....
    All the rest is just matter of what you need exactly and how you want to use the code Wink | ;)
    -----------------------------
    ejor @ http://dev.jesover.net

    Sign In · View Thread Well, you see, i started with the article, tried to implement exactly as the article suggested, but it didn't work, iwas always getting 0% for some reasons that i couldn't understand. So, i ended up taking the original code you wrote and throwing away the parts i didn't need. That told me the article wasn't complete...
    And this is what i got now, your own code simplified which i'm still not sure about how it works Smile | :) , it just does.
    Professional System Library on www.prosyslib.org

    Sign In · View Thread s_cpu[(s_index++) %5] = cpu;<br /> s_cpuProcess[(s_index++) %5] = cpuProcess;<br /> s_count ++;<br /> if ( s_count > 5 ) <br /> s_count = 5 ;<br />
    Was it intended for the s_index to be incremented twice per function call, and won't this cause an interleaving of values, somewhat modifying the result?
    Have I missed a cunning deliberate subtlety ?
    Yours, slightly baffled.
    Sign In · View Thread The author commented on this just up as "...just an heuristic to have something similar to task manager".
    Professional System Library on www.prosyslib.org

    Sign In · View Thread Member 4144649 is correct this is a little strange.
    the cpu usage array is filled in the order 0,2,4,1,3,0 ...
    and cpuProcess in the order 1,3,0,2,4 ...
    The first 4 calls don't use the complete array (not filled yet) to calculate the avarage.
    The first call uses only index 0 to calculate the avg. For cpuUsage it is not filled (started with 1).
    After 5 calls everything is OK. Luckly 5 is an odd number when using an even number it wouldn't work. (0,2,4,0,2,4 when using 6 instead of 5)
    It would be better when the code looks something like
    s_index++; s_index%= 5 ;
    Other improvment would be to have a method to retrieve the process cpu usage value (now only the system cpu usage is returned).
    Hope this message was helpfull, keep up the good work.
    Sign In · View Thread sorry to awaken this dead beast but i am having trouble compiling either pices of code, both the code in the article and the code provided by Vitaly Tomilov.
    when i try to compile the code from article it gives me the following error:
    \microsoft sdks\windows\v6.0a\include\sdkddkver.h(200) : fatal error C1012: unmatched parenthesis : missing ')'
    and when i try to compile the code given by by Vitaly Tomilov it gives me the following error:
    ..\ProcessorUsage.cpp|89|error: `CCritSecLock' was not declared in this scope|
    I would be most great full for any help!
    Sign In · View Thread CCritSecLock is a standard class from ATL. See file atlbase.h
    These are basics, that's probably why people don't bother answering.
    Professional System Library on www.prosyslib.org

    Sign In · View Thread in stdafx.h line 6,
    there is define:
    #define _WIN32_WINNT (0x0500) // WE ARE WinNT 5.0 SPECIFIC !!!
    block it.
    u should be able to compile original code i think, check it.
    I did.
    Sign In · View Thread if (hModule = GetModuleHandle(_T( " kernel32.dll" ))) if (s_pfnGetSystemTimes = (pfnGetSystemTimes)GetProcAddress(hModule, " GetSystemTimes" )) return ; if (!(hModule = GetModuleHandle(_T( " ntdll.dll" ))) return ; if (!(s_pfnNtQuerySystemInformation = (pfnNtQuerySystemInformation)GetProcAddress(hModule, " NtQuerySystemInformation" ))) return ; More readable and in case you want a return value you don't need an else for each if.
    Sign In · View Thread