用Pdh库获得CPU利用率

猛然碰到这个问题,在网上找了一些资料,现在综合一下,希望说的更明白。

一、API介绍:
1、PdhOpenQuery:获取性能监视器数据查询句柄(query);
2、PdhAddCounter:添加计数器;
3、PdhCollectQueryData:查询性能监视器数据;
4、PdhGetFormattedCounterValue:获取指定计数器数值;


可以用Pdh(performance data helper)库提供的一些函数来获取系统当前的一些性能数据(也可以读取日志文件获取之前的一些性能数据)。下面以以cpu的利用率为例介绍。

头文件: Pdh.h    (用#include<Pdh.h>包含)

静态链接库: Pdh.lib  (可以用宏语句 #pragma comment(lib,"Pdh.lib")来加载)

动态连接库: Pdh.dll (可以在主函数内用语句 HMODULE hModule=LoadLibraryEx("Pdh.dll",NULL,LOAD_LIBRARY_AS_DATAFILE)来加载动态连接库,用FreeLibrary(hModule)语句来释放动态连接库)

用Pdh库获得当前CPU利用率的步骤如下:

1、打开查询(query)句柄。

   HQUERY hquery; //声明查询句柄hquery

   PDHSTATUS pdhstatus=PdhOpenQuery(0,0,&hquery);

2、在查询中加入计数器(counter)(一个query中可以加入好几个counter,本例中之加入了一个counter)

   HCOUNTER* pdhcounter;   //计数器句柄的指针

   pdhcounter=(HCOUNTER*)GlobalAlloc(GPTR,(sizeof(HCOUNTER)));  //为计数器分配存储空间

   PdhAddCounter(hquery,"\\Processor Information(_Total)\\% Processor Time",0,pdhcounter);  //向查询hquery中加入计数器pdhcounter,函数的第二个参数是指定要加入什么样的技术器(就是在这里指定“cpu利用率”计数器),其格式是\\Computer\PerfObject(parent_instance/instance#index)\counter,其中,Computer指定要检测哪台计算机的性能,可以用ip地址指定网络中一台其他的计算机,本机时可以省略;PerfObject指定性能对象,即对哪类对象(可以是处理器(Processor Information),在其他系统中可能还可以是进程Process)进行检查,instance指定这类对象中的一个实例(如多个cpu时指定是哪个cpu(或者他们的和Total),对象是Process是可以指定是哪个进程等等),parent_instance和#index(index是数字,表示第几个instance)都是在只用instance无法识别是哪个进程时,需要加入的项(instance独一无二时,他们可以省略),counter指定前面指定的对象上的某个计数器(如Processor Information对象上有% Processor Time计数器,% Processor Time是一个整体,% 是计数器名字的一部分,要谨记的是%和P之间有一个空格,少写这个空格将找不到计数器)

    用GlobalAlloc()为pdhcounter分配的存储空间,当pdhcounter不再使用的时候,要用GlobalFree(pdhcounter)函数将其释放。

3、收集query的数据(query中的所有counter的数据都会被收集)

   PdhCollectQueryData(hquery);  //特别需要注意的是,用些counter数据(如rate、% Processor Time)需要Collect两次才能得到,有人遇到获取的cpu利用率总是0这个问题,那是因为虽然你用了两个PdhCollectQueryData()两次(否则会出错),但这两条相同的语句是紧挨着的,Pdh函数会计算这两个PdhCollectQueryData()之间这段时间的cpu利用率,所以将如两条语句紧挨着,那么这个间隔时间太短,所以得到的数据不太理想,解决办法是可以在两条PdhCollectQueryData()语句之间加入一条Sleep(50)语句,这样就可以得到50毫秒这段时间间隔内的cpu利用率,当然也可以加入一些其他的语句。

4、获得格式化(可以显示的)数据

   PdhCollectQueryData(hquery)函数获得的数据是原始数据(rawdata),可以用如下方法获得可显示的数据

   PDH_FMT_COUNTERVALUE pdh_counter_value;

   DWORD pdh_counter_value_type;

PdhGetFormattedCounterValu(*pdhcounter,PDH_FMT_DOUBLE,&pdh_counter_value_type,&pdh_counter_value);

pdh_counter_value.doublevalue中存的就是要得到的double值(当然,也可以获得LONG等其他类型的值)。

5、从query中删除不用的counter(一个query中可以加入好几个counter,本例中其实只加入了一个counter)

   PdhRemoveCounter(*pdhcounter);  //注意,不用指定是哪个query,因为counter信息中包含自己属于哪个query

6、关闭query(这会关闭query并且释放其中所有的counter及所占用的存储空间)

   PdhCloseQuery(hquery);

注1:以上某个步骤中的语句不是写程序中的精确顺序,只是从逻辑上写出了他们的顺序

注2:以上介绍的函数,都没有说个参数的具体含义,这些可以从MSDN官网上查,都有的

 

以下c++程序可以作为参考,在双核环境下获得某个cpu核的利用率:

#include<stdio.h>
#include<windows.h>
#include<Pdh.h>
#include<iostream>
#include<PDHMsg.h>

#pragma comment(lib, "Pdh.lib")
using namespace std;

void display_error(HMODULE hModule,DWORD pdhstatu)  //输出显示错误信息
{
  // HMODULE hModule;
     int error_count;
     LPVOID p_error_message;
  // hModule=LoadLibraryEx("Pdh.dll",NULL,LOAD_LIBRARY_AS_DATAFILE);
     if(hModule==NULL)
     {
         printf("hmodule is NULL\n");
         return;
     }
     error_count=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_IGNORE_INSERTS,hModule,pdhstatu,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &p_error_message,0,NULL);
     printf("%s",p_error_message);
     LocalFree(p_error_message);
  // FreeLibrary(hModule);
}
int main()
{
     HMODULE hModule1;
     HQUERY hquery=NULL;
     PDH_STATUS pdhstatus;
     HCOUNTER* pcounterhandle=NULL;
     PDH_FMT_COUNTERVALUE fmtcountervalue;
     DWORD pcountervaluetype;


     hModule1=LoadLibraryEx("Pdh.dll",NULL,LOAD_LIBRARY_AS_DATAFILE);
     if(hModule1==NULL)
     {
          printf("hmodule is NULL\n");
      }


     SetProcessAffinityMask(GetCurrentProcess(),0x00000001);  //把当前进程设置在某一个cpu上执行
     __try
     {
          pdhstatus=PdhOpenQuery(0,0,&hquery);
          if(pdhstatus!=ERROR_SUCCESS)
          {
              printf("open query error\n");
              display_error(hModule1,pdhstatus);
              __leave;
          }
          if(hquery==NULL)
          {
              printf("11\n");
          }
          pcounterhandle=(HCOUNTER*)GlobalAlloc(GPTR,sizeof(HCOUNTER));
      }
      __finally
      {
          if(AbnormalTermination())
          {
               printf("The try block of the terminate handle end abnormally\n");
          }
       }


      __try
      {
          pdhstatus=PdhAddCounter(hquery,"\\Processor Information(0,0)\\% Processor Time",0,pcounterhandle);
          if(pdhstatus!=ERROR_SUCCESS)
          {
              printf("addcounter err\n");
              display_error(hModule1,pdhstatus);
              __leave;
          }

           pdhstatus=PdhCollectQueryData(hquery);

           Sleep(50);

           pdhstatus=PdhCollectQueryData(hquery);
           if(pdhstatus!=ERROR_SUCCESS)
           {
               printf("collect query err\n");
               display_error(hModule1,pdhstatus);
               __leave;
           }


           pdhstatus=PdhGetFormattedCounterValue(*pcounterhandle,PDH_FMT_DOUBLE,&pcountervaluetype,&fmtcountervalue);
           if(pdhstatus!=ERROR_SUCCESS)
           {
               printf("get format data error\n");
               display_error(hModule1,pdhstatus);
               __leave;
            }
       }
       __finally
      {
            if(AbnormalTermination())
            {
                printf("The try block of termination handle terminate abnormal.\n");
             }
      }

      pdhstatus=PdhRemoveCounter(*pcounterhandle);
      if(pdhstatus!=ERROR_SUCCESS)
      {
             printf("remove counter error\n");
             display_error(hModule1,pdhstatus);
      }

      pdhstatus=PdhCloseQuery(hquery);
      if(pdhstatus!=ERROR_SUCCESS)
      {
             printf("close abnormally\n");
             display_error(hModule1,pdhstatus);
       }

      FreeLibrary(hModule1);
      return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用C++编写程序来获取CPU使用率。具体实现方式可能因操作系统而异,以下是在Windows操作系统下获取CPU使用率的示例代码: ```c++ #include <iostream> #include <windows.h> #include <pdh.h> #pragma comment(lib, "pdh.lib") int main() { PDH_HQUERY cpuQuery; PPDH_COUNTER_PATH_ELEMENTS pCounterPathElements = NULL; PDH_STATUS status; DWORD dwCounterPathSize; HCOUNTER cpuTotal; PDH_FMT_COUNTERVALUE counterVal; // 初始化 PDH 计数器 PdhOpenQuery(NULL, NULL, &cpuQuery); dwCounterPathSize = 0; status = PdhExpandCounterPath(L"\\Processor(_Total)\\% Processor Time", NULL, &dwCounterPathSize); pCounterPathElements = (PPDH_COUNTER_PATH_ELEMENTS)malloc(dwCounterPathSize); status = PdhExpandCounterPath(L"\\Processor(_Total)\\% Processor Time", pCounterPathElements, &dwCounterPathSize); PdhAddCounter(cpuQuery, pCounterPathElements->szFullPath, NULL, &cpuTotal); free(pCounterPathElements); // 获取 CPU 使用率 PdhCollectQueryData(cpuQuery); Sleep(1000); // 等待 1 秒 PdhCollectQueryData(cpuQuery); PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal); std::cout << "CPU 使用率:" << counterVal.doubleValue << "%" << std::endl; PdhCloseQuery(cpuQuery); return 0; } ``` 这段代码中,首先通过 PDH API 初始化计数器并添加要监控的计数器(这里是获取总CPU使用率),然后等待一秒钟后再次获取计数器值,并输出结果。你可以通过类似的方式在其他操作系统上实现获取 CPU 使用率的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值