[轉] Getting CPU Usage in a Multiprocessor Machine

出處:http://www.codeproject.com/Articles/10538/Getting-CPU-Usage-in-a-Multiprocessor-Machine

Introduction

Ever since I saw ‘Performance’ application on Windows 2000, I wondered if there is a way / Windows API to programmatically determine CPU usage for each of the individual CPUs in a multi-processor machine. Though there are many articles for getting the CPU usage, none helped when it came to multi-processor machines.
After some digging in MSDN, I could find WMI (Windows Management and Instrumentation) has a few performance counter classes. I chose to use the Win32_PerfRawData_PerfOS_Processor class in this case as it is supported on Windows 2000 onwards.

How to use it?

Follow these seven steps:
Step 1: Initialize COM:

CoInitializeEx(0, COINIT_MULTITHREADED);

Step 2: Set COM security levels:

CoInitializeSecurity(
        NULL, 
        -1,                          // COM authentication
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities 
        NULL                         // Reserved
        );

Step 3: Obtain the initial locator to WMI:

   IWbemLocator *pLoc = NULL;

   hres = CoCreateInstance(
        CLSID_WbemLocator,             
        0, 
        CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, (LPVOID *) &pLoc);

Step 4: Connect to WMI through the IWbemLocator::ConnectServer method:

    IWbemServices *pSvc = NULL;
 
    // Connect to the rootcimv2 namespace with
    // the current user and obtain pointer pSvc
    // to make IWbemServices calls.
    hres = pLoc->ConnectServer(
         _bstr_t(L"ROOTCIMV2"), // Object path of WMI namespace
         NULL,                    // User name. NULL = current user
         NULL,                    // User password. NULL = current
         0,                       // Locale. NULL indicates current
         NULL,                    // Security flags.
         0,                       // Authority (e.g. Kerberos)
         0,                       // Context object 
         &pSvc                    // pointer to IWbemServices proxy
         );

Step 5: Set security levels on the proxy:

CoSetProxyBlanket(
       pSvc,                        // Indicates the proxy to set
       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
       NULL,                        // Server principal name 
       RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
       RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
       NULL,                        // client identity
       EOAC_NONE                    // proxy capabilities 
    );

Step 6: Use the IWbemServices pointer to make requests of WMI:

    IEnumWbemClassObject* pEnumerator = NULL;
    HRESULT hres = pSvc->ExecQuery(
        bstr_t("WQL"), 
        bstr_t("SELECT * FROM Win32_PerfRawData_PerfOS_Processor"),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator);

Step 7: Get data from the query in step 6.

    IWbemClassObject *pclsObj;
    while (1)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);

        if(0 == uReturn)
        {
            break;
        }

          VARIANT vtProp;
          VariantInit(&vtProp);

          hr = pclsObj->Get(L"PercentProcessorTime", 0, &vtProp, 0, 0);

          // Use it

           hr = pclsObj->Get(L"TimeStamp_Sys100NS", 0, &vtProp, 0, 0);

          // Use it
    }

Note

I have tried to keep the source code in the attached project simple. So I have taken the number of processors as the input though you may like to programmatically get the number of processors using GetSystemInfo Win32 API.
I have tested it on Microsoft Windows 2000 Professional OS running on a dual processor machine. It should work on Windows XP/ Windows 2003 Server as well.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Author

BimalV


India India
No Biography provided
未經允許不得轉載:GoMCU » [轉] Getting CPU Usage in a Multiprocessor Machine