zoukankan      html  css  js  c++  java
  • 获取电脑实时CPU使用率

    要求:实现一个计算电脑实时CPU占有率的测试程序,将多种方法获取结果显示在对话框上,动态显示。

    实现:

    1、新建基于对话框的MFC应用程序,Dialog上添加控件,为控件添加CSting类型变量m_RateResult1、m_RateResult2、m_RateResult3,

          

    2、创建线程类(Thread.h和Thread.cpp),在 ####Dlg.cpp 文件中的初始化函数 OnInitDialog() 中创建计算CPU利用率的线程

        // TODO: 在此添加额外的初始化代码
    
        _beginthread(&CThread::InitCalcuPdh, 0, this);
        _beginthread(&CThread::InitCalcuGet, 0, this);
        _beginthread(&CThread::InitCalcuNt,  0, this);

    3、线程类中计算CPU利用率

    方式一:使用Performance Data Helper(PDH)性能数据助手,获取CPU利用率

     1 void CThread::InitCalcuPdh(void *pDlg)
     2 {
     3     CCalculateCPURateDlg *pItemDlg = (CCalculateCPURateDlg *)pDlg;
     4     if (pItemDlg == NULL)
     5     {
     6         return;
     7     }
     8 
     9     while(1)
    10     {
    11         //打开查询(query)句柄
    12         HQUERY query;
    13         PDH_STATUS status = PdhOpenQuery(NULL, NULL, &query);
    14         if (status != ERROR_SUCCESS)
    15         {
    16             pItemDlg->MessageBox(L"Open Query Error", NULL, MB_OK);
    17             continue;
    18         }
    19             
    20         //在查询中加入计数器(counter)
    21         HCOUNTER counter;
    22         //counter = (HCOUNTER *)GlobalAlloc(GPTR, sizeof(HCOUNTER));
    23         status = PdhAddCounter(query, LPCWSTR(L"\Processor Information(_Total)\% Processor Time"), NULL, &counter);
    24         if (status != ERROR_SUCCESS)
    25         {
    26             pItemDlg->MessageBox(L"Add Counter Error", NULL, MB_OK);
    27             continue;
    28         }
    29 
    30         //收集query的数据,在两条PdhCollectQueryData()语句之间加入一条Sleep(1000)语句
    31         PdhCollectQueryData(query);
    32         Sleep(1000);
    33         PdhCollectQueryData(query);
    34 
    35         //获得格式化(可以显示的)数据
    36         PDH_FMT_COUNTERVALUE pdhValue;
    37         DWORD dwValue;
    38         status = PdhGetFormattedCounterValue(counter, PDH_FMT_DOUBLE, &dwValue, &pdhValue);
    39         if (status != ERROR_SUCCESS)
    40         {
    41             pItemDlg->MessageBox(L"Get Value Error", NULL, MB_OK);
    42             continue;
    43         }
    44         pItemDlg->m_RateResult1.Format(L"%.0lf%%", pdhValue.doubleValue);
    45 
    46         SendMessage(pItemDlg->m_hWnd, WM_UPDATEDATA, FALSE, FALSE); 
    47         PdhCloseQuery(query);
    48     }
    49 }

    方式二:使用windows 自带的API(GetSystemTimes)获取CPU利用率

     1 __int64 DiffFileTime(FILETIME time1, FILETIME time2)
     2 {
     3     __int64 a = time1.dwHighDateTime << 32 | time1.dwLowDateTime;
     4     __int64 b = time2.dwHighDateTime << 32 | time2.dwLowDateTime;
     5     return (b - a);
     6 }
     7 void CThread::InitCalcuGet(void *pDlg)
     8 {
     9     CCalculateCPURateDlg *pItemDlg = (CCalculateCPURateDlg *)pDlg;
    10     if (pItemDlg == NULL)
    11     {
    12         return;
    13     }
    14 
    15     while(1)
    16     {
    17         double cpurate;
    18         __int64 idle, kernel, user;
    19         FILETIME preidleTime, idleTime;      //空闲时间
    20         FILETIME prekernelTime, kernelTime;  //内核态时间
    21         FILETIME preuserTime, userTime;      //用户态时间
    22 
    23         //计算CPU使用率,需要收集两份样本,中间用Sleep()函数间隔1s
    24         GetSystemTimes(&preidleTime, &prekernelTime, &preuserTime);
    25         Sleep(1000);
    26         GetSystemTimes(&idleTime, &kernelTime, &userTime);
    27 
    28         idle = DiffFileTime(preidleTime, idleTime);
    29         kernel = DiffFileTime(prekernelTime, kernelTime);
    30         user = DiffFileTime(preuserTime, userTime);
    31 
    32         if (kernel + user == 0)
    33             cpurate = 0.0;
    34         else
    35             cpurate = abs((kernel + user - idle) * 100 / (kernel + user));//(总的时间-空闲时间)/总的时间=占用cpu的时间就是使用率
    36         
    37         pItemDlg->m_RateResult2.Format(L"%.0lf%%", cpurate);
    38         SendMessage(pItemDlg->m_hWnd, WM_UPDATEDATA, FALSE, FALSE); 
    39     }
    40 }

    方式三:使用windows API(NtQuerySystemInformation)获取CPU利用率

     1 typedef struct _UINT64_DELTA
     2 {
     3     ULONG64 Value;
     4     ULONG64 Delta;
     5 } UINT64_DELTA, *PUINT64_DELTA;
     6 
     7 #define UpdateDelta(DltMgr, NewValue) 
     8 ((DltMgr)->Delta = (NewValue) - (DltMgr)->Value, 
     9 (DltMgr)->Value = (NewValue), (DltMgr)->Delta)
    10 
    11 void CThread::InitCalcuNt(void *pDlg)
    12 {
    13     CCalculateCPURateDlg *pItemDlg = (CCalculateCPURateDlg *)pDlg;
    14     if (pItemDlg == NULL)
    15     {
    16         return;
    17     }
    18 
    19     while(1)
    20     {
    21         double cpu_rate;
    22         ULONG64 total_time = 0;
    23         ULONG64 sys_time = 0;
    24         static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION CpuInformation[1024];
    25         static SYSTEM_INFO sys_info;
    26 
    27         static UINT64_DELTA cpu_kernel_delta;
    28         static UINT64_DELTA cpu_user_delta;
    29         static UINT64_DELTA cpu_idle_delta;
    30         static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION cpu_totals;
    31         memset(&cpu_totals, 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
    32 
    33         GetSystemInfo(&sys_info);
    34 
    35         NtQuerySystemInformation(
    36             SystemProcessorPerformanceInformation,
    37             &CpuInformation,
    38             sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * (ULONG)sys_info.dwNumberOfProcessors,
    39             NULL
    40             );
    41 
    42         for (int i = 0; i < (int)sys_info.dwNumberOfProcessors; i++)
    43         {
    44             SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION& cpu_info = CpuInformation[i];
    45 
    46             // KernelTime includes idle time.
    47             LONGLONG dpc_time = cpu_info.Reserved1[0].QuadPart;
    48             LONGLONG interrupt_time = cpu_info.Reserved1[i].QuadPart;
    49             cpu_info.KernelTime.QuadPart -= cpu_info.IdleTime.QuadPart;
    50             cpu_info.KernelTime.QuadPart += dpc_time + interrupt_time;
    51 
    52             cpu_totals.Reserved1[0].QuadPart += dpc_time;
    53             cpu_totals.IdleTime.QuadPart += cpu_info.IdleTime.QuadPart;
    54             cpu_totals.Reserved2 += cpu_info.Reserved2;
    55             cpu_totals.Reserved1[1].QuadPart += cpu_info.Reserved1[1].QuadPart;
    56             cpu_totals.KernelTime.QuadPart += cpu_info.KernelTime.QuadPart;
    57             cpu_totals.UserTime.QuadPart += cpu_info.UserTime.QuadPart;
    58         }
    59 
    60         UpdateDelta(&cpu_kernel_delta, cpu_totals.KernelTime.QuadPart);
    61         UpdateDelta(&cpu_user_delta, cpu_totals.UserTime.QuadPart);
    62         UpdateDelta(&cpu_idle_delta, cpu_totals.IdleTime.QuadPart);
    63 
    64         total_time = cpu_kernel_delta.Delta + cpu_user_delta.Delta + cpu_idle_delta.Delta;
    65         sys_time = cpu_kernel_delta.Delta + cpu_user_delta.Delta;
    66 
    67         if (total_time)
    68             cpu_rate = sys_time * 100.0 / total_time;
    69         else
    70             cpu_rate = 0.0;
    71         pItemDlg->m_RateResult3.Format(L"%.0lf%%", cpu_rate);
    72         Sleep(1000);
    73 
    74         SendMessage(pItemDlg->m_hWnd, WM_UPDATEDATA, FALSE, FALSE); 
    75     }
    76 }

    4、stdafx.h 中添加

    #pragma comment(lib,"pdh.lib")
    #pragma comment(lib,"ntdll.lib")
    #include <Pdh.h>
    #include <PdhMsg.h>
    #include <Windows.h> 
    #include <Winternl.h>

    错误:

    1、在线程中调用UpdateData函数,在Debug模式下编译可以通过,但运行时会触发中断

    原因:MFC对象不支持多线程操作,不能供多个线程进程使用。子线程调用pDlg-> UpdateData(FALSE)时主线程(界面线程)会阻塞,更新必须由它完成,这样就形成死锁。更改界面的操作最好用主线程(界面线程),要想在子线程(工作线程)里执行界面的操作,可以通过向主线程发送消息来解决。

    解决:

    ####Dlg.h 中添加

    #define WM_UPDATEDATA  10000+1
    
    afx_msg LRESULT OnUpdateData(WPARAM wParam, LPARAM lParam);

    ####Dlg.cpp 中添加

    ON_MESSAGE(WM_UPDATEDATA, OnUpdateData) 
    
    LRESULT CCalculateCPURateDlg::OnUpdateData(WPARAM wParam, LPARAM lParam) 
    { 
        UpdateData(wParam); 
        return 0; 
    } 

    Thread.cpp 中添加

    SendMessage(pItemDlg->m_hWnd, WM_UPDATEDATA, FALSE, FALSE);

    2、在某些环境中exe文件运行失败

    解决:Release使用MT选项编译,Debug使用MTd选项编译(同时属性页中选择在静态库中使用MFC)

    参考博客:

    https://www.cnblogs.com/einyboy/archive/2012/06/13/2548243.html

    http://www.cnblogs.com/hbccdf/p/get_sys_cpu_usage_and_mem_usage.html

  • 相关阅读:
    如何计算时间复杂度
    注意线程
    java中一个类要当作线程来使用有两种方法
    压缩和解压
    init [0123456]
    linux文件目录
    为什么使用combiner?【Hadoop】
    JAVA标识符
    关键字:java
    转 java 中int String类型转换
  • 原文地址:https://www.cnblogs.com/yapp/p/10098199.html
Copyright © 2011-2022 走看看