Linux下C语言获取cpu使用率
一、功能介绍通过读取/proc/stat文件获取当前系统的CPU占用率。
Linux系统上的/proc目录是一种文件系统,即proc文件系统,与其它常见的文件系统不同的是,/proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为内核与进程提供通信的接口。用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取/proc目录中的文件时,proc文件系统是动态从系统内核读出所需信息并提交的。
/proc/stat文件包含了所有CPU活动的信息,该文件中的所有值都是从系统启动开始累计到当前时刻。不同内核版本中该文件的格式可能不大一致。
获取电脑实时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利用率
方式一:使用PerformanceDataHelper(PDH)性能数据助手,获取CPU利用率
1voidCThread::InitCalcuPdh(void*pDlg)2{3CCalculateCPURateDlg*pItemDlg=(CCalculateCPURateDlg*)pDlg;4if(pItemDlg==NULL)5{6return;7}89while(1)10{11//打开查询(query)句柄12HQUERYquery;13PDH_STATUSstatus=PdhOpenQuery(NULL,NULL,&query);14if(status!=ERROR_SUCCESS)15{16pItemDlg->MessageBox(L"OpenQueryError",NULL,MB_OK);17continue;18}1920//在查询中加入计数器(counter)21HCOUNTERcounter;22//counter=(HCOUNTER*)GlobalAlloc(GPTR,sizeof(HCOUNTER));23status=PdhAddCounter(query,LPCWSTR(L"\ProcessorInformation(_Total)\%ProcessorTime"),NULL,&counter);24if(status!=ERROR_SUCCESS)25{26pItemDlg->MessageBox(L"AddCounterError",NULL,MB_OK);27continue;28}2930//收集query的数据,在两条PdhCollectQueryData()语句之间加入一条Sleep(1000)语句31PdhCollectQueryData(query);32Sleep(1000);33PdhCollectQueryData(query);3435//获得格式化(可以显示的)数据36PDH_FMT_COUNTERVALUEpdhValue;37DWORDdwValue;38status=PdhGetFormattedCounterValue(counter,PDH_FMT_DOUBLE,&dwValue,&pdhValue);39if(status!=ERROR_SUCCESS)40{41pItemDlg->MessageBox(L"GetValueError",NULL,MB_OK);42continue;43}44pItemDlg->m_RateResult1.Format(L"%.0lf%%",pdhValue.doubleValue);4546SendMessage(pItemDlg->m_hWnd,WM_UPDATEDATA,FALSE,FALSE);47PdhCloseQuery(query);48}49}方式二:使用windows自带的API(GetSystemTimes)获取CPU利用率
1__int64DiffFileTime(FILETIMEtime1,FILETIMEtime2)2{3__int64a=time1.dwHighDateTimem_hWnd,WM_UPDATEDATA,FALSE,FALSE);39}40}方式三:使用windowsAPI(NtQuerySystemInformation)获取CPU利用率
1typedefstruct_UINT64_DELTA2{3ULONG64Value;4ULONG64Delta;5}UINT64_DELTA,*PUINT64_DELTA;67#defineUpdateDelta(DltMgr,NewValue)8((DltMgr)->Delta=(NewValue)-(DltMgr)->Value,9(DltMgr)->Value=(NewValue),(DltMgr)->Delta)1011voidCThread::InitCalcuNt(void*pDlg)12{13CCalculateCPURateDlg*pItemDlg=(CCalculateCPURateDlg*)pDlg;14if(pItemDlg==NULL)15{16return;17}1819while(1)20{21doublecpu_rate;22ULONG64total_time=0;23ULONG64sys_time=0;24staticSYSTEM_PROCESSOR_PERFORMANCE_INFORMATIONCpuInformation[1024];25staticSYSTEM_INFOsys_info;2627staticUINT64_DELTAcpu_kernel_delta;28staticUINT64_DELTAcpu_user_delta;29staticUINT64_DELTAcpu_idle_delta;30staticSYSTEM_PROCESSOR_PERFORMANCE_INFORMATIONcpu_totals;31memset(&cpu_totals,0,sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));3233GetSystemInfo(&sys_info);3435NtQuerySystemInformation(36SystemProcessorPerformanceInformation,37&CpuInformation,38sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*(ULONG)sys_info.dwNumberOfProcessors,39NULL40);4142for(inti=0;im_RateResult3.Format(L"%.0lf%%",cpu_rate);72Sleep(1000);7374SendMessage(pItemDlg->m_hWnd,WM_UPDATEDATA,FALSE,FALSE);75}76}4、stdafx.h中添加
#pragmacomment(lib,"pdh.lib")#pragmacomment(lib,"ntdll.lib")#include#include#include#include
错误:
1、在线程中调用UpdateData函数,在Debug模式下编译可以通过,但运行时会触发中断
原因:MFC对象不支持多线程操作,不能供多个线程进程使用。子线程调用pDlg->UpdateData(FALSE)时主线程(界面线程)会阻塞,更新必须由它完成,这样就形成死锁。更改界面的操作最好用主线程(界面线程),要想在子线程(工作线程)里执行界面的操作,可以通过向主线程发送消息来解决。
解决:
####Dlg.h中添加
#defineWM_UPDATEDATA10000+1afx_msgLRESULTOnUpdateData(WPARAMwParam,LPARAMlParam);####Dlg.cpp中添加
ON_MESSAGE(WM_UPDATEDATA,OnUpdateData)LRESULTCCalculateCPURateDlg::OnUpdateData(WPARAMwParam,LPARAMlParam){UpdateData(wParam);return0;}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
C++获取CPU使用率
1、使用Ntdll.dll函数
NTSTATUSWINAPINtQuerySystemInformation(
_In_ SYSTEM_INFORMATION_CLASSSystemInformationClass,_Inout_ PVOIDSystemInformation,_In_ ULONGSystemInformationLength,_Out_opt_ PULONGReturnLength);计算CPU使用率的方法为查询SystemBasicInformation和SystemPerformanceInformation两个参数进行计算。
SYSTEM_BASIC_INFORMATION
Whenthe SystemInformationClass parameteris SystemBasicInformation,thebufferpointedtobythe SystemInformation parametershouldbelargeenoughtoholdasingleSYSTEM_BASIC_INFORMATION structurehavingthefollowinglayout:
typedefstruct_SYSTEM_BASIC_INFORMATION{BYTEReserved1[24];PVOIDReserved2[4];CCHARNumberOfProcessors;}SYSTEM_BASIC_INFORMATION;The NumberOfProcessors membercontainsthenumberofprocessorspresentinthesystem.Use GetSystemInfo insteadtoretrievethisinformation.
Theothermembersofthestructurearereservedforinternalusebytheoperatingsystem.
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
Whenthe SystemInformationClass parameteris SystemProcessorPerformanceInformation,thebufferpointedtobythe SystemInformation parametershouldbelargeenoughtoholdanarraythatcontainsasmany SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION structuresasthereareprocessors(CPUs)installedinthesystem.Eachstructurehasthefollowinglayout:
typedefstruct_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION{LARGE_INTEGERIdleTime;LARGE_INTEGERKernelTime;LARGE_INTEGERUserTime;LARGE_INTEGERReserved1[2];ULONGReserved2;}SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;The IdleTime membercontainstheamountoftimethatthesystemhasbeenidle,in100-nanosecondintervals.
The KernelTime membercontainstheamountoftimethatthesystemhasspentexecutinginKernelmode(includingallthreadsinallprocesses,onallprocessors),in100-nanosecondintervals.
The UserTime membercontainstheamountoftimethatthesystemhasspentexecutinginUsermode(includingallthreadsinallprocesses,onallprocessors),in100-nanosecondintervals.
Use GetSystemTimes insteadtoretrievethisinformation.
RemarksThe NtQuerySystemInformation functionandthestructuresthatitreturnsareinternaltotheoperatingsystemandsubjecttochangefromonereleaseofWindowstoanother.Tomaintainthecompatibilityofyourapplication,itisbettertousethealternatefunctionspreviouslymentionedinstead.
Ifyoudouse NtQuerySystemInformation,accessthefunctionthrough run-timedynamiclinking.Thisgivesyourcodeanopportunitytorespondgracefullyifthefunctionhasbeenchangedorremovedfromtheoperatingsystem.Signaturechanges,however,maynotbedetectable.
Thisfunctionhasnoassociatedimportlibrary.Youmustusethe LoadLibrary and GetProcAddress functionstodynamicallylinktoNtdll.dll.
使用该函数必须动态加载Ntdll.dll库和导出函数,使用起来比较麻烦。微软在XPsp1以后提供了新的API接口函数。上述两个参数可分别使用GetSystemInfo和GetSystemTimes函数代替。
详情参看MSDN:http://msdn.microsoft.com/en-us/library/ms724509.aspx
具体实现方法可以百度。
2、使用GetSystemTimes函数
//GetCpuUseage.h#includeclassGetCpuUseage{public:GetCpuUseage();~GetCpuUseage();public:doubleCpuUseage();private:FILETIMEm_preidleTime;FILETIMEm_prekernelTime;FILETIMEm_preuserTime;};
//GetCpuUseage.cpp#include"stdafx.h"#include"GetCpuUseage.h"__int64CompareFileTime(FILETIMEtime1,FILETIMEtime2){__int64a=time1.dwHighDateTime}doubleGetCpuUseage::CpuUseage(){FILETIMEidleTime;FILETIMEkernelTime;FILETIMEuserTime;GetSystemTimes(&idleTime,&kernelTime,&userTime);intidle=CompareFileTime(m_preidleTime,idleTime);intkernel=CompareFileTime(m_prekernelTime,kernelTime);intuser=CompareFileTime(m_preuserTime,userTime);if(kernel+user==0)return0.0;//(总的时间-空闲时间)/总的时间=占用cpu的时间就是使用率doublecpu=(kernel+user-idle)*100/(kernel+user);m_preidleTime=idleTime;m_prekernelTime=kernelTime;m_preuserTime=userTime;returncpu;}
调用方法:
#include"GetCpuUseage.h"
#include
intmain()
{
GetCpuUseagegetCpuUseage;
while(true)
{
printf("CPU使用率:%0.2f ",getCpuUseage.CpuUseage());
sleep(1000);
}
return0;
}
java应用cpu使用率过高问题排查
---------------------------------------linux下如何定位代码问题-------------------------------
1、先通过top命令找到消耗cpu很高的进程id假设是123
2、执行top-p123单独监控该进程
3、在第2步的监控界面输入H,获取当前进程下的所有线程信息
4、找到消耗cpu特别高的线程编号,假设是123
5、执行jstack123456对当前的进程做dump,输出所有的线程信息
6 将第4步得到的线程编号11354转成16进制是0x7b
7 根据第6步得到的0x7b在第5步的线程信息里面去找对应线程内容
8 解读线程信息,定位具体代码位置
-----------------------------分割线----------------------------------------------
最近在压力测试工作中碰到java应用某台机器cpu比较高的情况,特地下笔记以后总结:
一个简单的淘宝认证接口需要插入读写数据库2次。每次爬取数据,入库。完成。
正常情况下:
应用使用cpu在:50%--80%
压力高--异常情况下:
cpu利用率在:90%---90%
在网上查了下,一般java应用cpu过高基本上是因为
1.程序计算比较密集
2.程序死循环
3.程序逻请求堵塞4.IO读写太高
方法一:
分析步骤:
1.登陆应用机器,top-d1命令查看当前占用cpu资源最多的,一般排名第一位肯定是java进程
一般也可能存在多个java进程
观察top消耗第一的资源是PID=1679的线程
2.查看进程的哪个线程占用cpu比较高,取线上另外一台正常情况下利用cpu比较高的应用:通过
ps-mppid-oTHREAD,tid,time命令查看该进程的线程情况
通过以上线程CPU切片耗时在pid=1679Tid=1896耗时1分59秒,4%CPU占用最大。时间最长。
TID为1679的线程利用cpu资源比较多,怎么能看到这个线程在干什么呢?
需要将1896 转换为16进制,便于在jvm堆栈中查找。
printf"%x "1896 ----768
通过jstack命令来查看下当前内存状态:
定位到cpu过高是IO读写太高,接下来就是找开发人员确认这段代码是否可以优化。
方法二:
在做压测的时候,开发给了一个工具 show-busy-java-threads.sh
在排查Java的CPU性能问题时,找出Java进程中消耗cpu多(topus值过高)的线程,查看它的线程栈,从而找出有性能问题的方法调用。
####截取一段
#!/bin/bash#@Function#Findoutthehighestcpuconsumedthreadsofjava,andprintthestackofthesethreads.##@Usage#$./show-busy-java-threads.sh##@authorJerryLeereadonlyPROG=`basename$0`readonly-aCOMMAND_LINE=("$0""$@")usage(){cat