最近看到论坛中有人需要在Java端读取系统的CPU主频和使用率,在网上搜索了一下,发现了一些有用的东西,就在这总结一下。

一、获得CPU的主频

1、从注册表中读取

在注册表中键HKLM/HARDWARE/DESCRIPTION/System/CentralProcessor/0/~MHz对应的值为CPU的主频。

但是这种方法有一定的局限性,就是有的系统上没有这个键值。

2、通过写JNI调用汇编代码获得

//Cpuid.h 类声明 #ifndef _CPUID_H #define _CPUID_H #include <string> #include <windows.h> using namespace std; typedef unsigned long DWORD; typedef __int64 LONGLONG; class CPUID { public: CPUID(); virtual ~CPUID(); string GetVID(); //获取cpu制造商 string GetBrand(); //获取cpu型号 LONGLONG GetFrequency(DWORD sleepTime = 1000);//获取cpu主频 private: void Executecpuid(DWORD veax); //用以执行cpuid指令 DWORD m_eax; // 存储返回的eax DWORD m_ebx; // 存储返回的ebx DWORD m_ecx; // 存储返回的ecx DWORD m_edx; // 存储返回的edx }; #endif //Cpuid.cpp 类实现 #include "Cpuid.h" static const int S = sizeof(DWORD); CPUID::CPUID() :m_eax(0),m_ebx(0),m_ecx(0),m_edx(0) { } CPUID::~CPUID() { } void CPUID::Executecpuid(DWORD veax) { // 因为嵌入式的汇编代码不能识别 类成员变量 // 所以定义四个临时变量作为过渡 DWORD deax; DWORD debx; DWORD decx; DWORD dedx; __asm { mov eax, veax cpuid mov deax, eax mov debx, ebx mov decx, ecx mov dedx, edx } m_eax = deax; // 把临时变量中的内容放入类成员变量 m_ebx = debx; m_ecx = decx; m_edx = dedx; } string CPUID::GetVID() { char cVID[S*3+1]; // 字符串,用来存储制造商信息 memset(cVID, 0, sizeof(cVID)); // 把数组清0 Executecpuid(0); // 执行cpuid指令,使用输入参数 eax = 0 memcpy(cVID+S*0, &m_ebx, S); // 复制前四个字符到数组 memcpy(cVID+S*1, &m_edx, S); // 复制中间四个字符到数组 memcpy(cVID+S*2, &m_ecx, S); // 复制最后四个字符到数组 return string(cVID); // 以string的形式返回 } string CPUID::GetBrand() { const DWORD BRANDID = 0x80000002; // 从0x80000002开始,到0x80000004结束 char cBrand[S*4*3+1]; // 用来存储商标字符串,48个字符 memset(cBrand, 0, sizeof(cBrand)); // 初始化为0 for (DWORD i = 0; i < 3; i++) // 依次执行3个指令 { Executecpuid(BRANDID + i); // 每次执行结束后,保存四个寄存器里的asc码到数组 memcpy(cBrand + i*S*4 + S*0, &m_eax, S); memcpy(cBrand + i*S*4 + S*1, &m_ebx, S); memcpy(cBrand + i*S*4 + S*2, &m_ecx, S); memcpy(cBrand + i*S*4 + S*3, &m_edx, S); } return string(cBrand); // 以string的形式返回 } LONGLONG CPUID:: GetFrequency(DWORD sleepTime) { HANDLE hp = ::GetCurrentProcess(); //获取当前进程 HANDLE ht = ::GetCurrentThread(); //获取当前线程 DWORD pc = ::GetPriorityClass( hp ); //获取当前进程优先度 DWORD tp = ::GetThreadPriority( ht ); //获取当前线程优先度 BOOL flag1 = FALSE , flag2 = FALSE; DWORD low1 = 0 , high1 = 0 , low2 = 0 , high2 = 0; flag1 = ::SetPriorityClass( hp , REALTIME_PRIORITY_CLASS ); //将当前进程优先度设置最高 flag2 = ::SetThreadPriority( ht , THREAD_PRIORITY_HIGHEST ); //将当前线程优先度设置最高 ::Sleep( 10 ); LARGE_INTEGER fq,st,ed; ::QueryPerformanceFrequency(&fq); //精确计时 ::QueryPerformanceCounter(&st); //获得起始时间 __asm //获得当前cpu的时间周期数 { rdtsc mov low1 , eax mov high1 , edx } ::Sleep( sleepTime ); //将线程挂起片刻 ::QueryPerformanceCounter(&ed); //获得结束时间 __asm //获得当前cpu的时间周期数 { rdtsc mov low2 ,eax mov high2 ,edx } if( flag1 ) ::SetPriorityClass( hp , pc ); //将当前进程优先度恢复原样 if( flag2 ) ::SetThreadPriority( ht , tp ); //将当前线程优先度恢复原样 ::CloseHandle( hp ); ::CloseHandle( ht ); //将cpu的时间周期数转化成64位整数 LONGLONG begin = (LONGLONG)high1<<32 | low1; LONGLONG end = (LONGLONG)high2<<32 | low2; //将两次获得的cpu时间周期数除以间隔时间,即得到cpu的频率。 //由于windows的Sleep函数有大约15毫秒的误差,故以windows的精确计时为准 return (end - begin)*fq.QuadPart/(ed.QuadPart-st.QuadPart); } //Cpu.cpp 主cpp #include <iostream> #include "Cpuid.h" #define GHZ_UNIT (1000*1000*1000) #define MHZ_UNIT (1000*1000) int main() { CPUID cpu; string vid = cpu.GetVID(); cout<<vid<<endl; string brand = cpu.GetBrand(); cout<<brand<<endl; LONGLONG freq = cpu.GetFrequency(); if (freq > GHZ_UNIT) { double freqGHz = (double)freq/GHZ_UNIT; printf("%.2fGHz/n",freqGHz); //保留小数点后两位输出 } else { cout<<freq/MHZ_UNIT<<"MHz"<<endl; } cin.get(); return 0; }

3、通过CPUID来获取

#include <stdio.h> int main() { unsigned int eflags1, eflags2 = 0; unsigned int eax = 0; unsigned int ebx,ecx,edx; /** * 测试CPU是否支持CPUID指令。 * eflags寄存器的第21位,如果程序可以清楚/设置它,则说明CPU支持CPUID指令。否则不支持 */ /* 先取eflags */ asm volatile ("pushf/n/t" "popl %%eax" : "=a"(eflags1) : : "memory" ); printf("original eflags is %p/n", eflags1); /* 把eflags的第21位取反,写回寄存器中 */ asm volatile ("pushl %0/n/t" "popf" : : "g"(eflags1 & ~( eflags1 & (1<<21) ) ) ); /* 检查一下现在的eflags,确认第21位和最初的值相反 */ asm volatile ("pushf/n/t" "popl %%eax" : "=a"(eflags2) : : "memory" ); printf("modified eflags is %p/n", eflags2); /* 把原来的eflags值设置回去 */ asm volatile ("pushl %0/n/t" "popf" : : "g"(eflags1) ); /** * FIXME: Intel文档并没有说,如果不支持CPUID的话,clear/set eflags的第21位会有什么错误。 * 它只说,在不支持CPUID指令的CPU上,如80386,执行CPUID会产生invalid opcode错误 * * 所以,在这里我们不处理 读/写 eflags 第21比特失败的情形 */ /** * eax == 1,则在eax中返回Family/Model/Stepping等信息 * [0:3] stepping * [4:7] model * [8:11] family * [12:13] processor type * [16:19] extended model ID * [20:27] extended family ID */ asm volatile ("cpuid" : "=a"(eax) : "0"(1) ); // printf("eax is %p/n", eax); printf("Extended Family/t: %d/n", (0xff00000 & eax) >> 20); printf("Extended Model/t: %d/n", (0xf0000 & eax) >> 16); printf("Processor type/t: %d/n", (0x3000 & eax) >> 12); printf("Family/t/t: %d/n", (0xf00 & eax) >> 8); printf("Model/t/t: %d/n", (0xf0 & eax) >> 4); printf("Stepping:/t: %d/n", (0xf & eax)); printf("/n"); /** * eax == 0x800000000 * 如果CPU支持Brand String,则在EAX中返 >= 0x80000004的值。 */ asm volatile ("cpuid" : "=a"(eax) : "0"(0x80000000) ); printf("Is CPU support Brand String? %s/n", eax >= 0x80000004? "yes":"no"); printf("/n"); /** * 如果支持Brand String,则EAX从0x80000002到0x80000004,每次增1,CPUID指令返回: * EAX : Processor Brand String * EBX : Processor Brand String Continued * ECX : Processor Brand String Continued * EDX : Processor Brand String Continued */ if(eax >= 0x80000004) { unsigned int brands[4]; //每次的eax、ebx、ecx、edx unsigned int i; printf("Brand String/t: "); for (i = 0x80000002; i <= 0x80000004; i++) { asm volatile ("cpuid" : "=a"(brands[0]), "=b"(brands[1]), "=c"(brands[2]), "=d"(brands[3]) : "0" (i) ); printf("%s", (char *)brands); } //FIXME: 打出来的字符串是:In^Htel(R) Pentium(R^H) D CPU 2.80GHz //其中^H是个不可见字符,会把它前一个吃掉 printf("/n"); } /** * eax == 0 * eax : cpuid指令允许的最大eax输入值 * ebx : "Genu" * ecx : "ntel" * edx : "inel" */ asm volatile ("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "0"(0) ); printf("Maximum CPUID Input EAX : %p/n", eax); char string[128]; snprintf(string, 5, "%s", (char *)&ebx); snprintf(string + 4, 5, "%s", (char *)&edx); snprintf(string + 8, 5, "%s", (char *)&ecx); printf("Vendor/t/t: %s/n", string); printf("/n"); /** * eax == 1, * edx的第18比特为1,则CPU支持serial number * 为0,则不支持,或者被disabled * 序列号有96位,其中最高32位即是eax的输出值。应当把它保存下来,然后 * 再设置eax==3, 取剩下的64位 */ asm volatile ("cpuid" : "=a"(eax), "=d"(edx) : "a"(1) ); if ( edx & (1 << 18) ) { /* serial number supported */ /* edx输出中间32位的序列号,ecx输出最低32位的序列号 */ asm volatile ("cpuid" : "=c"(ecx), "=d"(edx) : "a"(3) ); printf("Serial Number/t : %x-%x-%x-%x-%x-%x/n", eax >> 16, eax << 16, edx >> 16, edx << 16, ecx >> 16, ecx << 16); } else printf("Serial Number not supported./n"); printf("/n"); /** * eax == 80000006h,返回L2 Cache的信息 * * ecx[31:16] : L2 Cache size, in Kbytes * ecx[15:12] : L2 Cache Associativity * 00h disabled * 01h direct mapped * 02h 2-Way * 04h 4-Way * 06h 8-Way * 08h 16-Way * 0Fh Fully associative * ecx[7:0] : L2 Cache Line size in bytes */ asm volatile ("cpuid" : "=c"(ecx) : "a"(0x80000006) ); printf("L2 Cache Size/t : %dKbytes/n", ( ecx >> 16 ) ); printf("L2 Cache Line Size/t : %dbytes/n", (ecx & 0xff)); printf("L2 Cache Associativity/t : "); switch ( (ecx & 0xf000) >> 12 ) { case 0x00: printf("%s/n", "disabled"); break; case 0x01: printf("%s/n", "direct mapped"); break; case 0x02: printf("%s/n", "2-Way"); break; case 0x04: printf("%s/n", "4-Way"); break; case 0x06: printf("%s/n", "8-Way"); break; case 0x08: printf("%s/n", "16-Way"); break; case 0x0f: printf("Fully associative"); break; default: printf("No such entry.../n"); } printf("/n"); /** * Input : eax == 4 && ecx == 0 * * (eax[31:26] + 1) 是该物理处理器package上实现的core CPUs数目 */ asm volatile ("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "0"(4), "2"(0) ); printf("Number of Cores on this physical package/t : %d/n", (eax >> 27) + 1 ); printf("/n"); /** * Input : eax == 1,则edx返回feature flag * */ return 0; }

二、获得CPU使用率

参考http://www.java2000.net/p11161

如何获取CPU的主频和使用率?相关推荐

  1. C# 使用 PerformanceCounter 获取 CPU 和 硬盘的使用率

    C# 使用 PerformanceCounter 获取 CPU 和 硬盘的使用率: 先看界面: 建一个 Windows Form  桌面程序,代码如下: using System; using Sys ...

  2. VC++获取CPU的名称、主频和核数(附源码)

    有时我们需要获取CPU的主频和核数(物理核数和逻辑核数)等信息去判断PC的性能,本文我们就介绍如何去获取这些信息. 1.获取CPU名称和主频 CPU的主频及名称等信息均存储在注册表中,可以到下列注册表 ...

  3. 编程获得CPU的主频

    CPU的主频,即CPU内核工作的时钟频率(CPU Clock Speed).CPU的主频表示在CPU内数字脉冲信号震荡的速度.主频和实际的运算速度存在一定的关系,但目前还没有一个确定的公式能够定量两者 ...

  4. openstack资源统计监控系列之ceilometer+gnocchi获取cpu、memory项目实战及实现源码(三)

    在做openstack资源统计监控中通过ceilometer+gnocchi获取cpu.memory的使用率,遇到了很多的坑,在一下分别记录,并附上实现的源码. 自从openstack发布到 S 版本 ...

  5. ios android cpu占用率,iPhone-iOS-从应用程序获取CPU使用率

    iPhone-iOS-从应用程序获取CPU使用率 有谁知道如何获取应用程序的CPU使用率? 绝对有可能,因为应用商店中有一些可以显示它的应用程序(活动监视器触摸). 3个解决方案 74 votes 更 ...

  6. Windows获取CPU、内存和磁盘使用率脚本

    获取CPU使用率脚本(vbs),另存为cpu.vbs: On Error Resume Next Set objProc = GetObject("winmgmts:\\.\root\cim ...

  7. 如何在 .NET Core 中获取 CPU 使用率

    这篇文章我们分享一种如何在 .NETCore 中获取 CPU使用率的方法, 它所报告的这个值和 任务管理器 中报告的 CPU 使用值 差不多是一致的. 在 .NET Framework 中,很多人会用 ...

  8. java获取网络带宽_Linux Java 获取CPU使用率,内存使用率,磁盘IO,网络带宽使用率等等...

    /** * 获取带宽上传下载速度 * @return */ public String getNetWorkSpeed() { boolean result = false; String detai ...

  9. VB.NET工作笔记015---vb.net获取cpu使用率,内存使用率_未能找到具有指定类别名“Processor”、计数器名“% Processor Time”的性能计数

    vb.net获取系统CPU的使用率,和内存的使用率 获取cpu的使用率,用: performanceCounter1这个控件,一定要记得,写上Processor 这个: counterName cat ...

最新文章

  1. oracle 某天 减一天,案例一:shell脚本指定日期减去一天
  2. STM32固件库文件树及构成详解
  3. torch expand
  4. php+date+timezoe,PHP 字符串
  5. 深入解析QML引擎, 第4部分: 自定义解析器
  6. 滴滴java开发面试题_Java开发经典面试题(十二)
  7. WPFの操作文件浏览框几种方式
  8. python es 数据库 ik_Linux系统:centos7下搭建ElasticSearch中间件,常用接口演示
  9. java变换变量赋值_Java变量的类型转换
  10. SWISHMAX2脚本整理及Swishmax使用技巧
  11. github上的python爬虫_python爬虫入门(2):让你的github项目火起来
  12. [Stage3D]硬件加速的径向模糊
  13. Mysql 分组聚合实现 over partition by 功能
  14. java中list set map 的区别
  15. 分子模拟软件amber_薛定谔 autodock 分子动力学模拟GROMACS软件
  16. cpuz测试分数天梯图_2015最新cpu天梯图 cpu性能排行榜
  17. WIFI WDS不同应用模式简介
  18. 电驴显示没有连接服务器,电驴未连接到服务器
  19. ByteBuffer详解(大概2333)
  20. 202302|读书笔记——国图点滴

热门文章

  1. tk教主:个人成长_网络成长时:浏览器的故事
  2. 利用mathematica画多个函数图像
  3. 5-ipv6服务器之-dns
  4. 现货交易、远期合同交易和期货交易
  5. 刷脸支付帮商户降低人力成本引流圈客
  6. java防止文件上传_文件上传漏洞:getshell的最好方式,我们如何防御?
  7. 【Java】9、Java IO 流
  8. 高通,MTK,紫光展锐 CPU超大核,大核,小核分布查询 以及绑定
  9. RN新架构 JSI 介绍
  10. LBS的概念、历史、现状与未来(一)