CPUID获取本机CPU信息

目录

  • 问题
  • 分析
  • 代码
  • 运行结果

问题

请使用Visual Studio编写一个控制台程序,功能如下:

一、使用命令CPUInfo.exe -C读取本机CPU信息,并存储到INI格式文本中:
示例如下:
[CPU]
Manufacturer = AuthenticAMD
BrandID = AMD Athlon Gold 3150U with Radeon Graphics
CPUID = 0F81
Cores = 2
HyperThread = True
MainClock = 2396MHZ

L1CacheSize = 192KB
L2CacheSize = 1024KB
L3CacheSize = 4096KB

二、使用命令CPUInfo.exe -r 读取INI文本中的CPU信息,并打印在控制台上;

分析

cpuid使用eax作为输入参数,eax,ebx,ecx,edx作为输出参数。

1、获取CPU的制造商信息
把eax = 0作为输入参数,可以得到CPU的制造商信息。
cpuid指令执行以后,会返回一个12字符的制造商信息,前四个字符的ASC码按低位到高位放在ebx,中间四个放在edx,最后四个字符放在ecx。

2、获取CPU商标信息(Brand String)
由于商标的字符串很长(48个字符),所以不能在一次cpuid指令执行时全部得到,所以intel把它分成了3个操作,eax的输入参数分别是0x80000002,0x80000003,0x80000004,每次返回的16个字符,按照从低位到高位的顺序依次放在eax, ebx, ecx, edx。因此,可以用循环的方式,每次执行完以后保存结果,然后执行下一次cpuid。

3、检测CPU特性(Hyper-Threading)
数是eax = 1,返回值放在edx,edx的bit 28代表是否支持Hyper-Threading

4、获得cpu的缓存(cache)
缓存信息包括:第几级缓存(level),缓存大小(size),通道数(way),吞吐量(line size)。因此可以使用一个结构体来存储缓存信息。

缓存信息可以通过eax = 2的cpuid来得到
返回值在eax(高24位), ebx, ecx和edx,总共15个BYTE的信息

5、获取cpu的序列号
CPU的序列号用一个96bit的串表示,格式是连续的6个WORD值:XXXX-XXXX-XXXX-XXX-XXXX-XXXX。
获得序列号需要两个步骤,首先用eax = 1做参数,返回的eax中存储序列号的高两个WORD。用eax = 3做参数,返回ecx和edx按从低位到高位的顺序存储前4个WORD。

参考:c++获得cpu厂商_在C++中使用cpuid指令获得CPU信息

代码

软件实现过程:

1、定义三个结构体,分别存储缓存信息、序列号和CPU信息。
2、定义一个类,获取CPU制造商,商标、id序列号信息,是否支持Hyper Thread,定义四个DWORD变量,分别存储返回的eax、ebx、ecx、edx。在类的重构函数中定义临时变量,并且将临时变量的内容放入类成员变量作为初始化。
3、编写功能函数,获取CPU信息,并且将信息写入ini格式文本存储,并且可以读取和清除ini文本内容,在存储文本路径中使用函数获取当前执行文件的路径,方便ini格式文本的创建和读取等操作。
4、测试程序。

// ReadCpuInfo.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
/*
请使用Visual Studio编写一个控制台程序,功能如下:一、使用命令CPUInfo.exe -C读取本机CPU信息,并存储到INI格式文本中:
示例如下:
[CPU]
Manufacturer = AuthenticAMDBrandID = AMD Athlon Gold 3150U with Radeon Graphics
CPUID = 0F81
Cores = 2
HyperThread = True
MainClock = 2396MHZ
L1CacheSize = 192KB
L2CacheSize = 1024KB
L3CacheSize = 4096KB二、使用命令CPUInfo.exe -r 读取INI文本中的CPU信息,并打印在控制台上;wmic cpu get processorid   ----------powershell查看CPUID
dxdiag ----------------DirectX诊断工具查看电脑配置
systeminfo查看电脑配置*/
#include <iostream>
#include<string>
#include<map>
#include<Windows.h>
#include<intrin.h>
#include<thread>
#include <vector>
#include<sstream>
#include<fstream>
#include<algorithm>
#include<iomanip>
#include <atlstr.h>using namespace std;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;typedef BOOL(WINAPI* LPFN_GLPI)(LOGICAL_PROCESSOR_RELATIONSHIP,PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD);//缓存信息
struct CacheInfo
{int level;    // 第几级缓存int size;    // 缓存大小,单位KBCacheInfo()    // 构造函数{level = 0;size = 0;}CacheInfo(int clevel, int csize)  // 构造函数{level = clevel;size = csize;}};//序列号/ID号
struct Serialnumber {  WORD nibble[6];Serialnumber() {memset(nibble, 0, sizeof(nibble));  //复制字符串}
};//cpu信息
struct CpuInfo
{string vID;string bID;string SeriNum;int cores;string HThread;double Mainclock;
};class CPUID
{public:static CPUID* Instance();static CPUID* m_pInstance;map<int, CacheInfo> m_cache; // Cache information tablevirtual ~CPUID();string GetVID();                //获取CPU制造商信息string GetBrand();              //获取CPU商标信息string Getserialnumber();      //获取ID序列号string IsHyperThreading();           //是否支持HyperThreadprivate:void Executecpuid(DWORD eax); // 用来实现cpuidDWORD m_eax;   // 存储返回的eaxDWORD m_ebx;   // 存储返回的ebxDWORD m_ecx;   // 存储返回的ecxDWORD m_edx;   // 存储返回的edx};CPUID* CPUID::m_pInstance = NULL;CPUID* CPUID::Instance()
{if (NULL == m_pInstance)     // if instance is not present, create a new instance{m_pInstance = new CPUID();}return m_pInstance;
}CPUID::~CPUID()
{delete m_pInstance;        // delete instancem_pInstance = NULL;      // set the pointer to NULL
}void CPUID::Executecpuid(DWORD veax)
{// 因为嵌入式的汇编代码不能识别 类成员变量// 所以定义四个临时变量作为过渡DWORD deax;DWORD debx;DWORD decx;DWORD dedx;__asm{mov eax, veax;// 将输入参数移入eaxcpuid;         // 执行cpuidmov deax, eax; //以下四行代码把寄存器中的变量存入临时变量mov debx, ebx;mov decx, ecx;mov dedx, edx;}m_eax = deax; // 把临时变量中的内容放入类成员变量m_ebx = debx;m_ecx = decx;m_edx = dedx;}//获取cpu核心数
int GetCores()
{//注释:因为这里HyperThread的缘故,所以4核读成8核心//方式一//SYSTEM_INFO sysInfo;//GetSystemInfo(&sysInfo);//cout << "Cores = " << sysInfo.dwNumberOfProcessors /2 << endl;//方式二unsigned int nCpu = max(std::thread::hardware_concurrency(), (unsigned int)1);//  cout << "Cores = " << nCpu / 2 << endl;return (nCpu);
}//获取cpu的主频信息
double GetMainClock()
{static int time[2];              //定义一个整型数组timeint  a = 0;                   //定义整形变量a=0(在后面的运算中用来存商)int  b = 0;                   //定义整形变量b=0(在后面的运算中用来存余数)double sum = 0;__asm {rdtsc;                    //RDTSC指令,意思是读取时间标记计数器(Read Time-Stamp Counter)mov ecx, offset time;          //将time的偏移地址存入ecxmov[ecx + 0], edx;            //把TSC的值的高32位存入[ecx+0]中mov[ecx + 4], eax;            //把TSC的值的低32位存入[ecx+4]中}Sleep(1000);                  //延时1秒__asm {rdtsc;mov ebx, offset time;            //将time的偏移地址存入ebxsub eax, [ebx + 4];             //把延时1秒后的TSC值的高32位减去1秒前的TSC值的高32位sbb edx, [ebx + 0];             //把延时1秒后的TSC值的低32位减去1秒前的TSC值的低32位mov ecx, 1000000000;div ecx;               //将2次TSC差值除以1,000,000,000mov a, eax;mov b, edx;}b = b / 100000000;b = b * 10;// cout << "MainClock = " << a << "." << b << "GHz" << endl;sum = (a * 100 + b);sum = sum / 100;//cout << sum << endl;return sum;
}//初始化除cpu三级缓存之外的其它信息
CpuInfo* init()
{CpuInfo* CInfo = new CpuInfo[2];CPUID* info = CPUID::Instance();CInfo[0].vID = info->GetVID();CInfo[0].bID = info->GetBrand();CInfo[0].SeriNum = info->Getserialnumber();CInfo[0].cores = GetCores();CInfo[0].HThread = info->IsHyperThreading();CInfo[0].Mainclock = GetMainClock();return CInfo;
}//获得CPU的制造商信息(Vender ID String)
//把eax = 0作为输入参数,可以得到CPU的制造商信息。
string CPUID::GetVID()
{char cVID[13];   // 字符串,用来存储制造商信息memset(cVID, 0, 13);  // 把数组清0Executecpuid(0);  // 执行cpuid指令,使用输入参数 eax = 0memcpy(cVID, &m_ebx, 4); // 复制前四个字符到数组memcpy(cVID + 4, &m_edx, 4); // 复制中间四个字符到数组memcpy(cVID + 8, &m_ecx, 4); // 复制最后四个字符到数组return string(cVID);  // 以string的形式返回
}//获得CPU商标信息(Brand String)
string CPUID::GetBrand()
{const DWORD BRANDID = 0x80000002;  // 从0x80000002开始,到0x80000004结束char cBrand[49];    // 用来存储商标字符串,48个字符memset(cBrand, 0, 49);    // 初始化为0for (DWORD i = 0; i < 3; i++)   // 依次执行3个指令{Executecpuid(BRANDID + i);memcpy(cBrand + i * 16, &m_eax, 16); // 每次执行结束后,保存四个寄存器里的asc码到数组}      // 由于在内存中,m_eax, m_ebx, m_ecx, m_edx是连续排列// 所以可以直接以内存copy的方式进行保存return string(cBrand);  // 以string的形式返回
}//获取ID序列号
string CPUID::Getserialnumber() {string serialnumber;char num[32];memset(num, 0, 32);Executecpuid(1);sprintf_s(num, 32, "%08X", m_edx);serialnumber = serialnumber + num;//memcpy(&serial.nibble[4], &m_eax, 4);sprintf_s(num, 32, "%08X", m_eax);serialnumber = serialnumber + num;//memcpy(&serial.nibble[0], &m_ecx, 8);return serialnumber;
}// 判断是否支持hyper-threading
string CPUID::IsHyperThreading()
{bool HyperThread;string str;Executecpuid(1);  // 执行cpuid指令,使用输入参数 eax = 1HyperThread = (m_edx & (1 << 28));if (!HyperThread){//   cout << "HyperThread = False" << endl;str = "False";return str;}else{//  cout << "HyperThread = Ture" << endl;str = "Ture";return str;}// return m_edx & (1 << 28);  // 返回edx的bit 28
}//获取cpu三级缓存信息
CacheInfo*  GetCacheInfo()
{CacheInfo* cpuCache = new CacheInfo[3];int L1 = 0;int L2 = 0;int L3 = 0;LPFN_GLPI glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformationEx");if (!glpi)return NULL;DWORD bytes = 0;glpi(RelationAll, 0, &bytes);vector<char> buffer(bytes);SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* info;if (!glpi(RelationAll, (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)&buffer[0], &bytes))return NULL;for (size_t i = 0; i < bytes; i += info->Size){info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)&buffer[i];if (info->Relationship == RelationCache &&(info->Cache.Type == CacheData ||info->Cache.Type == CacheUnified)){if ((int)info->Cache.Level == 1){L1 += (int)info->Cache.CacheSize;}if ((int)info->Cache.Level == 2){L2 += (int)info->Cache.CacheSize;}if ((int)info->Cache.Level == 3){L3 += (int)info->Cache.CacheSize;}}}//cout << "L1CacheSize = " << L1 * 2 / 1024 << "KB" << endl;//cout << "L2CacheSize = " << L2 / 1024 << "KB" << endl;//cout << "L3CacheSize = " << L3 / 1024 << "KB" << endl;cpuCache[0].level = 1;cpuCache[0].size = L1 * 2 / 1024;cpuCache[1].level = 2;cpuCache[1].size = L2 / 1024;cpuCache[2].level = 3;cpuCache[2].size = L3 / 1024;return cpuCache;
}//将获取的cpu信息写进INI文档
void WriteInfo(CpuInfo *CInfo,CacheInfo* cpuCache)
{int i = 0;//自动获取文本地址CString path;GetModuleFileName(NULL, path.GetBufferSetLength(MAX_PATH + 1), MAX_PATH);path.ReleaseBuffer();int pos = path.ReverseFind('\\');path = path.Left(pos);path = path + L"\\cpuINfoTest.ini";ofstream ofs;ofs.open(path, ios::out | ios::app);if (!ofs){cout << "Open file error" << endl;return;}ofs << "[CPU]" << endl;ofs << "Manufacturer = " << CInfo[i].vID << endl;ofs << "BrandID = " << CInfo[i].bID << endl;ofs << "CPUID = " << CInfo[i].SeriNum << endl;ofs << "Cores = " << CInfo[i].cores << endl;ofs << "HyperThread =" << CInfo[i].HThread << endl;ofs.setf(ios::fixed);ofs << "MainClock = " << fixed << setprecision(2) << CInfo[i].Mainclock << "GHz" << endl;  //保留两位小数点ofs << "L" << cpuCache[0].level << "CacheSize = " << cpuCache[0].size << "KB" << endl;ofs << "L" << cpuCache[1].level << "CacheSize = " << cpuCache[1].size << "KB" << endl;ofs << "L" << cpuCache[2].level << "CacheSize = " << cpuCache[2].size << "KB" << endl;ofs << "\n";cout << "\n ini file write success!" << endl;ofs.close();return;
}//从INI格式文本中读取内容
void ReadInfo(CpuInfo* CInfo, CacheInfo* cpuCache)
{int n = 0;ifstream ifs;CString path;GetModuleFileName(NULL, path.GetBufferSetLength(MAX_PATH + 1), MAX_PATH);path.ReleaseBuffer();int pos = path.ReverseFind('\\');path = path.Left(pos);path = path + L"\\cpuINfoTest.ini";ifs.open(path, ios::in);if (!ifs){cout << "Open file error" << endl;return;}string str;while (!ifs.eof())           //读到文件结束{getline(ifs, str);cout << str << endl;}cout << "\n" << endl;cout << "read file success" << endl;ifs.close();return;
}//打印需要获取的CPU信息
void display(CpuInfo* CInfo, CacheInfo* cpuCache)
{int i = 0;cout << "[CPU]" << endl;cout << "Manufacturer = " << CInfo[i].vID << endl;cout << "BrandID = " << CInfo[i].bID << endl;cout << "CPUID = " << CInfo[i].SeriNum << endl;cout << "Cores = " << CInfo[i].cores << endl;cout << "HyperThread =" << CInfo[i].HThread << endl;cout.setf(ios::fixed);                            cout << "MainClock = " << fixed << setprecision(2) << CInfo[i].Mainclock  << "GHz" << endl;  //保留两位小数点cout << "L" << cpuCache[0].level << "CacheSize = " << cpuCache[0].size << "KB" << endl;cout << "L" << cpuCache[1].level << "CacheSize = " << cpuCache[1].size << "KB" << endl;cout << "L" << cpuCache[2].level << "CacheSize = " << cpuCache[2].size << "KB" << endl;return;
}//清空INI文本内容
void fileEmpty()
{CString path;GetModuleFileName(NULL, path.GetBufferSetLength(MAX_PATH + 1), MAX_PATH);path.ReleaseBuffer();int pos = path.ReverseFind('\\');path = path.Left(pos);path = path + L"\\cpuINfoTest.ini";fstream file;fstream open(path, ios::out | ios::binary);cout << "INI文本内容已成功清除内容" << endl;return;
}//用户提示功能
void showhelp()
{cout << "--------------------------------------------" << endl;cout << "欢迎使用本系统" << endl;cout << "需要按照以下提示输入才可以实现对应功能\n" << endl;cout << "C: 读取本机CPU信息,并存储到INI格式文本" << endl;cout << "R:读取INI文本中的CPU信息,并显示" << endl;cout << "L: 清空存储CPU信息的INI文本内容" << endl;cout << "exit: 退出系统" << endl;cout << "--------------------------------------------" << endl;cout << "\n";
}int main(int argc, char* argv[])
{CpuInfo* cpuInfo =  init();CacheInfo* cache = GetCacheInfo();showhelp();if (argc == 2){if (strcmp(argv[1], "C") == 0 || strcmp(argv[1], "c") == 0){display(cpuInfo, cache);WriteInfo(cpuInfo, cache);}else if (strcmp(argv[1], "R") == 0 || strcmp(argv[1], "r") == 0){ReadInfo(cpuInfo, cache);}else if (strcmp(argv[1], "L") == 0 || strcmp(argv[1], "l") == 0){fileEmpty();}else if (strcmp(argv[1], "exit") == 0){//return -1;exit(0);}else{cout << "输入错误,请根据showhelp提示输入 " << endl;return 0;//   showhelp();//   system("pause");}}else{cout << "输入错误,请根据showhelp提示输入 " << endl;// showhelp();system("pause");}
}// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

运行结果




看到这里就结束了,希望你今天仍然美好

需要cpuid.pdf的读者可私信

CPUID获取本机CPU信息相关推荐

  1. java 通过snmp协议获取物理机CPU、内存容量及使用率,存储的容量及使用率

    java 用snmp协议获取物理机CPU.内存容量及使用率,存储的容量及使用率,java获取trap告警 一.SNMP简介 1.什么是snmp 二.SNMP获取信息步骤 1.开启SNMP 2.MIB文 ...

  2. 获取本机CPU,硬盘等使用情况

    早上的时候接到主管的一个任务,要获取服务器上的cpu,硬盘, 数据库等 的使用情况,并以邮件的方式发给boss, = =没办法,公司的服务器真是不敢恭维,顺便吐槽一下公司的网速,卡的时候30k左右徘徊 ...

  3. QT学习:获取本机网络信息

    获取本机网络信息,具体实现方法如下: (1)头文件"networkinformation.h"的具体代码如下: #include <QWidget> #include ...

  4. [Qt教程] 第35篇 网络(五)获取本机网络信息

    [Qt教程] 第35篇 网络(五)获取本机网络信息 楼主  发表于 2013-9-5 11:32:58 | 查看: 278| 回复: 2 获取本机网络信息 版权声明 该文章原创于作者yafeilinu ...

  5. Qt网络获取本机网络信息

    下面我们就讲解如何获取自己电脑的IP地址以及其他网络信息.这一节中,我们会涉及到网络模块(QtNetwork Module)中的QHostInfo ,QHostAddress ,QNetworkInt ...

  6. [转载]Qt之获取本机网络信息

    原文地址:Qt之获取本机网络信息作者:一去丶二三里 经常使用命令行来查看一些计算机的配置信息. 1.首先按住键盘上的"开始键+R键",然后在弹出的对话框中输入"CMD&q ...

  7. [转载]Qt之获取本机网络信息_vortex_新浪博客

    原文地址:Qt之获取本机网络信息作者:一去丶二三里 经常使用命令行来查看一些计算机的配置信息. 1.首先按住键盘上的"开始键+R键",然后在弹出的对话框中输入"CMD&q ...

  8. 第35篇 网络(五)获取本机网络信息

    导语 前面讲完了HTTP和FTP,下面本来该讲解UDP和TCP了.不过,在讲解它们之前,我们先在这一节里讲解一个以后要经常用到的名词,那就是IP地址. 对于IP地址,其实,会上网的人都应该听说过它.如 ...

  9. java使用siger 轻松获取本机硬件信息(CPU 内存 网络 io等)

    1.下载sigar.jar sigar官方主页 sigar-1.6.4.zip 2.按照主页上的说明解压包后将相应的文件copy到java路径.比如windows32位操作系统需要将lib中sigar ...

最新文章

  1. 转载iOS开发中常见的警告及错误
  2. 成功解决ValueError: `bins` must be positive, when an integer
  3. 【WC2018】通道【边分治】【虚树】【树的直径】
  4. 阿里弹性云手机正式公测
  5. 已知平面上两点坐标及半径,求过两点圆弧的圆心坐标
  6. 软件测试相关英文单词整理
  7. LiteIDE简单使用
  8. java指数运算_java算法-指数运算(大数运算)
  9. [人工智能-深度学习-32]:卷积神经网络CNN - 常见分类网络- AlexNet网络结构分析与详解
  10. Stellarium:诱人的星相不雅察软件
  11. 浅谈无线路由器自动掉线解决办法
  12. MATLAB添加噪声
  13. 孙陶然:公司要与员工分享
  14. 2010-2020管理类联考MBA/MEM英语大作文范文模版
  15. 洛谷 P5459 [BJOI2016]回转寿司 【CDQ分治】
  16. #榜样的力量#思必驰疫情防控机器人丨数据猿新冠战“疫”公益策划
  17. C++出租车公司管理系统
  18. hive-学习汽车销售分析
  19. 企业数字化转型 有“后台”就是硬
  20. 网络宣传策划无所不用其极啊

热门文章

  1. p20华为云电脑白屏_强大的华为云电脑真的可以让我们彻底丢掉电脑?
  2. 光模块SFP+与SFP、XFP、QSFP、QSFP+的区别
  3. 综述|2021最新关于点云配准的全面介绍
  4. Result Maps collection already contains value for com.hry.igoods.mapper.TbAreaMapper.BaseResultMap
  5. 修改mysql初始密码时报错:ERROR 1064 (42000): You have an error in your SQL syntax
  6. 2019年运维想比别人月薪多赚10K?那就一定要选门编程语言了!
  7. debian 9 ssh root权限登录
  8. 自定义可存数据的jquery 表情输入框
  9. 开源PLog库的使用
  10. [从头读历史] 第272节 诗经 齐风