Linux下使用C++获取硬件信息

目录

  • 方法
  • 获取CPU信息:读取"/proc/cpuinfo"文件
  • 获取磁盘信息:读取"/proc/diskstats"文件
  • 获取BIOS信息有两种方法:1、读取文件;2、使用dmidecode命令
  • 获取主板信息有两种方法:1、读取文件;2、使用dmidecode命令
  • 代码部分
  • 代码链接
  • 部分运行结果

方法

通过读取Linux下存放硬件信息的文件来获取CPU、主板、磁盘、BIOS信息

获取CPU信息:读取"/proc/cpuinfo"文件

在这里插入图片描述

字段及其含义:

处理器基本信息:

  • processor:处理器的逻辑编号,从 0 开始,用于标识系统中的每个逻辑 CPU。
  • vendor_id:CPU制造商的标识符。例如,对于 Intel CPU,可能是GenuineIntel;对于 AMD CPU,可能是AuthenticAMD。

处理器型号与家族信息

  • cpu family:CPU 所属的家族编号。不同家族的 CPU 可能具有不同的架构和特性。例如,Intel 的酷睿系列和至强系列可能属于不同的家族。
  • model:CPU型号编号,结合cpu family可以更准确地确定 CPU 的具体型号。
  • model name:CPU 的完整型号名称,提供了详细的 CPU 型号描述,如Intel® Core™ i7-10700K CPU @ 3.80GHz。

步进与微代码信息:

  • stepping:CPU的步进编号,它标识了 CPU 的修订版本。不同的步进可能包含对之前版本的错误修复或性能改进。
  • microcode:CPU微代码版本号,微代码是嵌入在 CPU 中的一小段代码,用于协助 CPU 执行指令,可以通过更新微代码来修复 CPU 的一些问题或提升性能。

性能相关信息:

  • cpu MHz:CPU当前的运行频率,单位为 MHz。这可能是动态变化的,尤其是在支持节能技术(如 Intel 的 SpeedStep 或 AMD 的
    Cool’n’Quiet)的 CPU 上。
  • cache size:CPU 缓存的大小,通常以 KB 或 MB 为单位。缓存可以提高 CPU 访问数据的速度,较大的缓存通常意味着更好的性能。

多处理器与多核信息:

  • physical id:物理处理器的标识符。在多处理器系统中,每个物理 CPU 有一个唯一的physical id。
  • siblings:同一物理 CPU上的逻辑处理器数量,即超线程技术下每个物理核心对应的逻辑核心数。例如,如果一个物理核心支持超线程,siblings可能为 2。
  • core id:每个物理核心的唯一标识符,在同一物理 CPU 内,不同的物理核心有不同的core id。
  • cpu cores:每个物理 CPU 中的核心数量,不包括超线程产生的逻辑核心。

其他信息:

  • apicid:高级可编程中断控制器(APIC)标识符,用于多处理器系统中的中断处理。
  • flags:CPU支持的特性标志列表,每个标志表示 CPU 支持的一种特定功能或指令集,如mmx、sse、sse2等,这些指令集可以加速特定类型的计算任务。
  • bogomips:代表 “BogusMIPS(伪每秒百万条指令数)”。它是一种对 CPU 性能的近似估计值,并非基于实际指令执行的精确测量。这个数值最初由 Linus Torvalds引入 Linux 内核,作为一种快速且相对简单的方法来评估 CPU 的处理能力。
  • clflush size:缓存行刷新(Cache Line Flush)操作所涉及的缓存行大小。

获取磁盘信息:读取"/proc/diskstats"文件

在这里插入图片描述
字段及其含义(从左至右):

  1. 主设备号(Major device number):在示例中为8,它标识设备类型。例如,8通常代表SCSI 磁盘设备。不同的设备类型有不同的主设备号,可用于识别设备所属的大类。
  2. 次设备号(Minor device number):示例中的0,它用于在同一主设备类型下进一步区分具体的设备实例。主设备号和次设备号共同唯一标识系统中的一个块设备。
  3. 设备名称(Device name):这里是sda,这是设备在系统中的名称,通常对应/dev目录下的设备文件名,方便用户和系统管理员识别和操作具体设备。
  4. 读完成次数(Reads completed successfully):212553,表示从设备成功完成的读操作次数。每次成功读取数据块,该计数增加。
  5. 读合并次数(Reads merged):14992,系统有时会合并相邻的读请求以提高 I/O 效率,该字段统计了合并读操作的次数。合并读可以减少I/O 操作的总次数,提升性能。
  6. 读扇区数(Sectors read):1469963,表示从设备读取的扇区总数。一个扇区通常是 512 字节(在现代设备中也可能是 4096字节等),这个数字反映了读取的数据量(以扇区为单位)。
  7. 读操作花费的毫秒数(Time spent reading (ms)):334512,累计花费在读操作上的时间,以毫秒为单位。它反映了设备读取数据所花费的总时间,可用于评估读性能。
  8. 写完成次数(Writes completed successfully):1005650,表示向设备成功完成的写操作次数。每次成功写入数据块,该计数增加。
  9. 写合并次数(Writes merged):121259,类似于读合并,系统会合并相邻的写请求,该字段统计了合并写操作的次数,以提高写性能。
  10. 写扇区数(Sectors written):6743707,表示向设备写入的扇区总数,反映了写入的数据量(以扇区为单位)。
  11. 写操作花费的毫秒数(Time spent writing (ms)):10052256,累计花费在写操作上的时间,以毫秒为单位,可用于评估写性能。
  12. 当前I/O 操作数(I/O requests currently in progress):0,表示当前正在进行的 I/O
    请求数量。如果这个值持续不为零,可能表示设备出现了 I/O 瓶颈。
  13. I/O操作花费的总毫秒数(Time spent doing I/O (ms)):343049,累计花费在所有 I/O
    操作(读和写)上的时间,以毫秒为单位。
  14. 加权的I/O 操作花费的毫秒数(Weighted time spent doing I/O (ms)):10386768,这是一个加权时间,考虑了I/O 请求的排队时间等因素,能更全面地反映 I/O 操作对系统资源的占用情况。

获取BIOS信息有两种方法:1、读取文件;2、使用dmidecode命令

一、读取文件

可以通过读取三个文件分别获得BIOS供应商名称、BIOS版本号、BIOS发布日期,分别是:

BIOS供应商名称:/sys/class/dmi/id/bios_vendor

BIOS版本号:/sys/class/dmi/id/bios_version

BIOS发布日期:/sys/class/dmi/id/bios_date

优点:

  • 无需 root 权限​​:普通用户即可访问。
  • 无额外依赖​​:直接通过文件接口读取,避免调用外部命令。
  • ​​适用于容器/虚拟化环境​​:即使 DMI 信息被限制,部分字段仍可能可用。

缺点:获取到的信息少。

二、使用dmidecode命令

工作方式:dmidecode的工作方式就是解析DMI表

命令:sudo dmidecode -t bios

在这里插入图片描述
字段含义:

  • Vendor:BIOS供应商名称
  • Version:BIOS版本号
  • Release Date:BIOS发布日期
  • Address:BIOS在内存中的物理地址(十六进制)
  • Runtime Size​:BIOS运行时占用的内存大小
  • ROM Size:存储 BIOS固件的 ROM(只读存储器)容量
  • Characteristics:BIOS支持的特性列表,每个特性对应一个硬件或软件功能
  • ​​BIOS Revision​:BIOS 的修订版本号(可能与 Version 不同)
  • Firmware Revision​:主板固件的版本号(可能与 BIOS 版本分离)

优点: 获取的信息更多、更全面。

缺点:​

  • 权限要求​​:dmidecode 需要 ​​root 权限​​ 才能读取完整 DMI表,如果运行程序的用户不是root用户会失败。
  • 依赖性​​:dmidecode方法需要安装该工具(通常默认已安装),常见的安装目录。有"/usr/sbin/dmidecode"、“/sbin/dmidecode”、“/usr/local/sbin/dmidecode”。代码在调用命令前需要先验证是否存在路径。
  • 适用性​​:虚拟化环境(如容器)中可能无法提供完整的DMI信息。

获取主板信息有两种方法:1、读取文件;2、使用dmidecode命令

一、读取文件

可以通过读取文件分别获得主板供应商名称、主板版本号、主板型号,主板序列号,主板资产标签分别是:

主板供应商名称:/sys/class/dmi/id/board_vendor

主板版本号:/sys/class/dmi/id/board_version

主板型号:/sys/class/dmi/id/board_name

主板序列号:/sys/class/dmi/id/board_serial,读取该文件需要root权限,所以代码中无法依靠读取文件获取,但是可以通过dmidecode命令获取(见下文)

主板资产标签:/sys/class/dmi/id/board_asset_tag

优点:

  • 无需 root 权限​​:普通用户即可访问。
  • 无额外依赖​​:直接通过文件接口读取,避免调用外部命令。
  • ​​适用于容器/虚拟化环境​​:即使 DMI 信息被限制,部分字段仍可能可用。

缺点: 获取到的信息少。

二、使用dmidecode命令

工作方式:dmidecode的工作方式就是解析DMI表

命令:sudo dmidecode -t baseboard

在这里插入图片描述
字段含义:

  • Manufacturer:主板制造商

  • Product Name: 主板型号

  • Version:主板版本号,None为未指定

  • Serial
    Number:主板序列号,None为未指定

  • Asset Tag: 资产标签,Not Specified为未指定

  • Features:主板特殊功能,None为无特殊功能

  • Location In Chassis:主板在机箱中的位置,Not Specified未记录

  • Chassis Handle:关联的机箱记录句柄,0x0000为未关联或默认值

  • Type:主板类型,Unknown为未明确

  • Contained Object Handle:关联的子设备,0表示无关联

优点: 获取的信息更多、更全面。

缺点:​

  • 权限要求​​:dmidecode 需要 ​​root 权限​​ 才能读取完整 DMI表,如果运行程序的用户不是root用户会失败。
  • 依赖性​​:dmidecode方法需要安装该工具(通常默认已安装),常见的安装目录。有"/usr/sbin/dmidecode"、“/sbin/dmidecode”、“/usr/local/sbin/dmidecode”。代码在调用命令前需要先验证是否存在路径。
  • 适用性​​:虚拟化环境(如容器)中可能无法提供完整的DMI信息。

代码部分

// LinuxHardwareInfo.h#pragma once#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <string.h>
#include <sstream>
#include <memory>
#include <stdexcept>
#include <array>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <unordered_map>
#include <functional>// CPU信息结构体
struct CPUInfo
{std::string processor_;              // CPU 的逻辑编号std::string vendor_id_;              // CPU 制造商的标识符std::string cpu_family_;             // CPU 所属的家族编号std::string model_;                  // CPU 型号编号std::string model_name_;             // CPU 的完整型号名称std::string stepping_;               // CPU 的步进编号std::string microcode_;              // CPU 微代码版本号std::string cpu_freq_;               // CPU 当前的运行频率,单位为 MHzstd::string cache_size_;             // CPU 缓存的大小,单位为KBstd::string physical_id_;            // CPU 的标识符std::string siblings_;               // 同一物理 CPU 上的逻辑处理器数量std::string core_id_;                // 每个物理核心的唯一标识符std::string cpu_cores_;              // 每个物理 CPU 中的核心数量,不包括超线程产生的逻辑核心std::string clflush_size_;           // 缓存行刷新(Cache Line Flush)操作所涉及的缓存行大小
};// 磁盘信息结构体
struct DiskStatsInfo
{std::string major_device_num_;          // 主设备号,标识设备类型std::string minor_device_num_;          // 次设备号,用于在同一主设备类型下进一步区分具体的设备实例,主设备号和次设备号共同唯一标识系统中的一个块设备std::string device_name_;               // 磁盘名称,对应/dev目录下的设备文件名std::string read_completed_;            // 从设备成功完成的读操作次数,每次成功读取数据块,该计数增加std::string read_merged_;               // 合并读操作次数std::string read_sectors_;              // 从设备读取的扇区总数std::string read_time_spent_;           // 累计花费在读操作上的时间,单位毫秒std::string write_completed_;           // 向设备成功完成的写操作次数,每次成功写入数据块,该计数增加std::string write_merged_;              // 合并写操作次数std::string write_sectors_;             // 向设备写入的扇区总数std::string write_time_spent_;          // 累计花费在写操作上的时间,单位毫秒
};// BIOS信息结构体,细节信息通过dmidecode命令获取到的
struct BIOSMoreInfo
{// 基础信息std::string     vendor_;                    // BIOS供应商std::string     version_;                   // BIOS版本std::string     date_;                      // BIOS发布日期// 细节信息std::string   address_;                     // BIOS 在内存中的物理地址(十六进制)std::string   runtime_size_;                // BIOS运行时占用的内存大小,单位为bytesstd::string   rom_size_;                    // 存储 BIOS 固件的 ROM(只读存储器)容量,单位为kBstd::string   bios_revision_;               // BIOS的修订版本号,可能与Version不同std::string   firmware_revisioin_;          // 主板固件版本号
};// 主板信息结构体,细节信息通过dmidecode命令获取
struct BaseboardMoreInfo
{// 基础信息std::string     vendor_;                    // 主板供应商std::string     version_;                   // 主板版本号std::string     name_;                      // 主板型号std::string     asset_tag_;                 // 主板资产标签// 细节信息std::string     serial_num_;                // 主板序列号std::string     location_in_chassis_;       // 主板在机箱中的位置std::string     type_;                      // 主板类型
};// 检测当前运行环境是否可以使用dmidecode命令
#ifndef IsUseDmidecodeCommand
#define IsUseDmidecodeCommand()\bool is_use_dmidecode = false;\\if(geteuid() == 0 && FindDmidecodePath())\is_use_dmidecode = true;\else\std::cout << "当前运行环境不支持dmidecode命令, 只获取基本信息" << std::endl;
#endif// 根据:进行字符串切割并去除两端空格得到key和value字符串
#ifndef SplitRemoveWhite
#define SplitRemoveWhite(_line)\size_t pos = _line.find(':');\\if (pos == std::string::npos)\return;\\std::string key = _line.substr(0, pos);\std::string value = _line.substr(pos + 1);\\RemoveWhiteSpace(value);\RemoveWhiteSpace(key);
#endif// Linux下获取CPU的所有信息
class LinuxHardwareInfo
{
public:LinuxHardwareInfo();~LinuxHardwareInfo();/*@brief 获取CPU的所有信息@param _cpu_infos 会有多个cpu的信息*/void GetProcessorAllInfo(std::vector<CPUInfo>& _cpu_infos);/*@brief 获取磁盘的所有信息@param _disk_infos 会有多个磁盘信息*/void GetDiskStatsAllInfo(std::vector<DiskStatsInfo>& _disk_infos);/*@brief 获取BIOS的信息1、该接口会先使用demidecode命令获取BIOS更详细的信息,如果检测到系统的demidecode命令无法使用,改用读取文件的方式只获取BISO基本信息!!!2、该接口返回true的情况为:Linux系统已经安装demidecode命令,并且运行程序的用户为root用户@param _bios_info BIOS信息结构体@return true表示demidecode命令可以使用,获取到了更详细的信息;false说明当前运行环境的demidecode命令无法使用,只能获取基本信息。*/bool GetBIOSAllInfo(BIOSMoreInfo& _bios_info);/*@brief 获取主板的信息1、该接口会先使用demidecode命令获取BIOS更详细的信息,如果检测到系统的demidecode命令无法使用,改用读取文件的方式只获取主板基本信息!!!2、该接口返回true的情况为:Linux系统已经安装demidecode命令,并且运行程序的用户为root用户@param _board_info 主板信息结构体@return true表示demidecode命令可以使用,获取到了更详细的信息;false说明当前运行环境的demidecode命令无法使用,只能获取基本信息。*/bool GetBoardAllInfo(BaseboardMoreInfo& _board_info);private:/*@brief 通过读取文件的方式获取BIOS基本信息@param BIOS基本信息*/void GetBIOSBasicInfo(BIOSMoreInfo& _bios_info);/*@brief 通过读取文件的方式获取主板基本信息@param 主板基本信息*/void GetBoardBasicInfo(BaseboardMoreInfo& _board_info);/*@brief 去除字符串两端的空白字符,包括空格、\t等@param _str 源字符串*/void RemoveWhiteSpace(std::string& _str);/*@brief 解析CPU文件信息的一行@param _line 一行字符串@param _cpu_info 存储数据的结构体*/void ParseProcessorLine(const std::string& _line, CPUInfo& _cpu_info);/*@brief 处理BISO信息的一行@param _line 一行字符串@param _bios_info BISO数据结构体*/void ProcessBIOSLine(const std::string& _line, BIOSMoreInfo& _bios_info);/*@brief 处理主板信息的一行@param _line 一行字符串@param _board_info 主板数据结构体*/void ProcessBoardLine(const std::string& _line, BaseboardMoreInfo& _board_info);/*@brief 检查 dmidecode 是否存在并返回其完整路径@return true表示存在,false表示不存在*/bool FindDmidecodePath();/*@brief 执行命令并捕获输出@param cmd 命令@return 输出的字符串*/std::string GetStrByCommand(const char* _cmd);/*@brief 按照换行符进行切割@param _str 源字符串@return 切割后的集合*/std::vector<std::string> SplitByNewline(const std::string& _str);/*@brief 更新主板结构体处理器@param _key 结构体成员对应的key值@param value 结构体成员值*/void UpdateBoardInfo(BaseboardMoreInfo& _board_info, const std::string& _key, const std::string& _value);/*@brief 更新BIOS结构体处理器@param _key 结构体成员对应的key值@param value 结构体成员值*/void UpdateBIOSInfo(BIOSMoreInfo& _bios_info, const std::string& _key, const std::string& _value);/*@brief 更新CPU结构体处理器@param _key 结构体成员对应的key值@param value 结构体成员值*/void UpdateCpuInfo(CPUInfo& _cpu_info, const std::string& _key, const std::string& _value);private:// 成员指针类型别名using BoardMemberPtr = std::string BaseboardMoreInfo::*;using BIOSMemberPtr = std::string BIOSMoreInfo::*;using CpuMemberPtr = std::string CPUInfo::*;const std::string cpu_file_;        // Linux系统下cpu信息的存储路径const std::string disk_file_;       // Linux系统下磁盘信息的存储路径const std::string bios_dir_;                             // Linux系统下存放BIOS信息的目录const std::vector<std::string>  bios_files_name_;        // Linux系统下存放BIOS信息的所有文件名const std::string board_dir_;                             // Linux系统下存放主板信息的目录const std::vector<std::string>  board_files_name_;        // Linux系统下存放主板信息的所有文件名const std::vector<std::string>  dmidecode_command_path_; // Linux系统下常见的demidecode命令的完整路径,检测系统是否安装该命令会用到std::unordered_map<std::string, std::function<void(std::string)>>   process_board_value_map_;           // 给主板信息结构体赋值    
};
// LinuxHardwareInfo.cpp
#include "LinuxHardwareInfo.h"LinuxHardwareInfo::LinuxHardwareInfo(): cpu_file_("/proc/cpuinfo"), disk_file_("/proc/diskstats"), bios_dir_("/sys/class/dmi/id/"), bios_files_name_({"bios_vendor","bios_version","bios_date"}), dmidecode_command_path_({"/usr/sbin/dmidecode", "/sbin/dmidecode", "/usr/local/sbin/dmidecode"}), board_dir_("/sys/class/dmi/id/"), board_files_name_({"board_vendor","board_version","board_name","board_asset_tag"})
{
}LinuxHardwareInfo::~LinuxHardwareInfo()
{
}void LinuxHardwareInfo::GetProcessorAllInfo(std::vector<CPUInfo> &_cpu_info)
{std::ifstream file(cpu_file_);if (!file.is_open()){std::cerr << "CPU文件: " << cpu_file_ << "打开失败" << std::endl;return;}CPUInfo cpuInfo;std::string line;while (std::getline(file, line)){if (line.empty()){// 读取下一个cpu的信息if(!cpuInfo.model_name_.empty()) {_cpu_info.push_back(cpuInfo);cpuInfo = CPUInfo();}}elseParseProcessorLine(line, cpuInfo);}// 添加最后一个CPU信息if (!cpuInfo.model_name_.empty()) {_cpu_info.push_back(cpuInfo);}file.close();
}void LinuxHardwareInfo::GetDiskStatsAllInfo(std::vector<DiskStatsInfo> &_disk_infos)
{std::ifstream disk_stats_file(disk_file_);if (!disk_stats_file.is_open()) {std::cerr << "磁盘文件: " << disk_file_ << "打开失败" << std::endl;return;}std::string line;while (std::getline(disk_stats_file, line)){std::istringstream iss(line);DiskStatsInfo diskStats;std::string inFlight, ioTicks, timeInQueue;if (!(iss >> diskStats.major_device_num_ >> diskStats.minor_device_num_ >> diskStats.device_name_>> diskStats.read_completed_ >> diskStats.read_merged_ >> diskStats.read_sectors_>> diskStats.read_time_spent_ >> diskStats.write_completed_ >> diskStats.write_merged_ >> diskStats.write_sectors_ >> diskStats.write_time_spent_ >> inFlight >> ioTicks >> timeInQueue)) {continue;}_disk_infos.push_back(diskStats);}disk_stats_file.close();return;
}bool LinuxHardwareInfo::GetBIOSAllInfo(BIOSMoreInfo &_bios_info)
{IsUseDmidecodeCommand()if(is_use_dmidecode)   // 使用dmidecode命令获取更详细的BISO信息{try{// 对获取到的命令输出进行字符串切割std::vector<std::string> bios_info_vec = SplitByNewline(GetStrByCommand("dmidecode -t bios"));for(const auto& line : bios_info_vec){ProcessBIOSLine(line, _bios_info);}} catch (const std::exception& e){std::cerr << "dmidecode命令执行错误: " << e.what() << std::endl;// 抛出异常后只获取基本信息GetBIOSBasicInfo(_bios_info);return false;}}else    // 只获取基本信息GetBIOSBasicInfo(_bios_info);return is_use_dmidecode;
}bool LinuxHardwareInfo::GetBoardAllInfo(BaseboardMoreInfo &_board_info)
{IsUseDmidecodeCommand()if(is_use_dmidecode)   // 使用dmidecode命令获取更详细的主板信息{try{// 对获取到的命令输出进行字符串切割std::vector<std::string> board_info_vec = SplitByNewline(GetStrByCommand("dmidecode -t baseboard"));bool is_parse = false;for(const auto& line : board_info_vec){if(line == "Base Board Information")is_parse = true;else if(line.empty())is_parse = false;if(is_parse)ProcessBoardLine(line, _board_info);}} catch (const std::exception& e){std::cerr << "dmidecode命令执行错误: " << e.what() << std::endl;// 抛出异常后只获取基本信息GetBoardBasicInfo(_board_info);return false;}}else    // 只获取基本信息GetBoardBasicInfo(_board_info);return is_use_dmidecode;
}void LinuxHardwareInfo::GetBIOSBasicInfo(BIOSMoreInfo &_bios_info)
{for(const auto& file_name : bios_files_name_){// bios文件路径std::string path = bios_dir_ + file_name;std::ifstream file(path);if (!file.is_open()){std::cerr << "BIOS文件: " << path << "打开失败" << std::endl;return;}std::string value;std::getline(file, value);UpdateBIOSInfo(_bios_info,file_name,value);}
}void LinuxHardwareInfo::GetBoardBasicInfo(BaseboardMoreInfo &_board_info)
{for(const auto& file_name : board_files_name_){// board文件路径std::string path = board_dir_ + file_name;std::ifstream file(path);if (!file.is_open()){std::cerr << "主板文件: " << path << "打开失败" << std::endl;return;}std::string value;std::getline(file, value);UpdateBoardInfo(_board_info,file_name,value);}
}void LinuxHardwareInfo::RemoveWhiteSpace(std::string &_str)
{int head_idx = 0, tail_idx = _str.length() - 1;bool head_flag = false, tail_flag = false;while (head_idx != tail_idx){// 使用std::isspace方法判断空白字符,因为会有\t等情况if(!head_flag && std::isspace(_str[head_idx]))head_idx++;elsehead_flag = true;if(!tail_flag && std::isspace(_str[tail_idx]))tail_idx--;elsetail_flag = true;if(head_flag && tail_flag)break;}_str = _str.substr(head_idx, tail_idx - head_idx + 1);return;
}void LinuxHardwareInfo::ParseProcessorLine(const std::string &_line, CPUInfo &_cpu_info)
{SplitRemoveWhite(_line)UpdateCpuInfo(_cpu_info,key,value);
}void LinuxHardwareInfo::ProcessBIOSLine(const std::string &_line, BIOSMoreInfo &_bios_info)
{SplitRemoveWhite(_line)UpdateBIOSInfo(_bios_info,key,value);
}void LinuxHardwareInfo::ProcessBoardLine(const std::string &_line, BaseboardMoreInfo &_board_info)
{SplitRemoveWhite(_line)UpdateBoardInfo(_board_info,key,value);
}bool LinuxHardwareInfo::FindDmidecodePath()
{for (const auto& path : dmidecode_command_path_) {if (access(path.c_str(), X_OK) == 0) {return true; // 找到有效路径}}return false;
}std::string LinuxHardwareInfo::GetStrByCommand(const char *_cmd)
{std::array<char, 128> buffer;std::string result;std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(_cmd, "r"), pclose);if (!pipe) {throw std::runtime_error("Failed to execute command");}while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {result += buffer.data();}return result;
}std::vector<std::string> LinuxHardwareInfo::SplitByNewline(const std::string &_str)
{std::vector<std::string> lines;std::istringstream iss(_str);std::string line;   while (std::getline(iss, line, '\n')) {lines.push_back(line);}return lines;
}void LinuxHardwareInfo::UpdateBoardInfo(BaseboardMoreInfo &_board_info, const std::string &_key, const std::string &_value)
{static const std::unordered_map<std::string, BoardMemberPtr> keys_map = {{"Manufacturer",   &BaseboardMoreInfo::vendor_},{"Product Name",   &BaseboardMoreInfo::name_},{"Version",  &BaseboardMoreInfo::version_},{"Serial Number",       &BaseboardMoreInfo::serial_num_},{"Asset Tag",  &BaseboardMoreInfo::asset_tag_},{"Location In Chassis",    &BaseboardMoreInfo::location_in_chassis_},{"Type",    &BaseboardMoreInfo::type_},{"board_vendor",   &BaseboardMoreInfo::vendor_},{"board_name",   &BaseboardMoreInfo::name_},{"board_version",   &BaseboardMoreInfo::version_},{"board_asset_tag",   &BaseboardMoreInfo::asset_tag_},{"board_serial",   &BaseboardMoreInfo::serial_num_}};if (auto it = keys_map.find(_key); it != keys_map.end()) {_board_info.*(it->second) = _value;}// else//     std::cerr << "解析出" << _key << "和" << _value << std::endl;
}void LinuxHardwareInfo::UpdateBIOSInfo(BIOSMoreInfo &_bios_info, const std::string &_key, const std::string &_value)
{static const std::unordered_map<std::string, BIOSMemberPtr> keys_map = {{"Vendor",   &BIOSMoreInfo::vendor_},{"Release Date",   &BIOSMoreInfo::date_},{"Version",  &BIOSMoreInfo::version_},{"Address",       &BIOSMoreInfo::address_},{"Runtime Size",  &BIOSMoreInfo::runtime_size_},{"ROM Size",    &BIOSMoreInfo::rom_size_},{"BIOS Revision",    &BIOSMoreInfo::bios_revision_},{"Firmware Revision",    &BIOSMoreInfo::firmware_revisioin_},{"bios_vendor",   &BIOSMoreInfo::vendor_},{"bios_date",   &BIOSMoreInfo::date_},{"bios_version",   &BIOSMoreInfo::version_}};if (auto it = keys_map.find(_key); it != keys_map.end()) {// 部分字段带有单位,去除单位if(_value.find(" ") != std::string::npos){size_t pos = _value.find(" ");_bios_info.*(it->second) = _value.substr(0, pos);}else_bios_info.*(it->second) = _value;}// else//     std::cerr << "解析出" << _key << "和" << _value << std::endl;
}void LinuxHardwareInfo::UpdateCpuInfo(CPUInfo& _cpu_info, const std::string &_key, const std::string &_value)
{static const std::unordered_map<std::string, CpuMemberPtr> keys_map = {{"processor",   &CPUInfo::processor_},{"vendor_id",   &CPUInfo::vendor_id_},{"cpu family",  &CPUInfo::cpu_family_},{"model",       &CPUInfo::model_},{"model name",  &CPUInfo::model_name_},{"stepping",    &CPUInfo::stepping_},{"microcode",    &CPUInfo::microcode_},{"cpu MHz",    &CPUInfo::cpu_freq_},{"physical id",   &CPUInfo::physical_id_},{"siblings",   &CPUInfo::siblings_},{"core id",   &CPUInfo::core_id_},{"cpu cores",   &CPUInfo::cpu_cores_},{"clflush size",   &CPUInfo::clflush_size_}};if (auto it = keys_map.find(_key); it != keys_map.end()) {// 部分字段带有单位,去除单位if(_value.find(" ") != std::string::npos){size_t pos = _value.find(" ");_cpu_info.*(it->second) = _value.substr(0, pos);}else_cpu_info.*(it->second) = _value;}// else//     std::cerr << "解析出" << _key << "和" << _value << std::endl;
}
// main.cpp
#include <iostream>
#include "LinuxHardwareInfo.h"
int main()
{LinuxHardwareInfo info;std::cout << "*************************CPU信息*************************" << std::endl;std::vector<CPUInfo> cpuInfos;info.GetProcessorAllInfo(cpuInfos);for (const auto& cpuInfo : cpuInfos){std::cout << "-------------------------" << std::endl;std::cout << "processor: " << cpuInfo.processor_ << std::endl;std::cout << "Vendor ID: " << cpuInfo.vendor_id_ << std::endl;std::cout << "CPU Family: " << cpuInfo.cpu_family_ << std::endl;std::cout << "Model: " << cpuInfo.model_ << std::endl;std::cout << "Model Name: " << cpuInfo.model_name_ << std::endl;std::cout << "Stepping: " << cpuInfo.stepping_ << std::endl;std::cout << "Microcode: " << cpuInfo.microcode_ << std::endl;std::cout << "CPU MHz: " << cpuInfo.cpu_freq_ << std::endl;std::cout << "Cache Size: " << cpuInfo.cache_size_ << std::endl;std::cout << "Physical ID: " << cpuInfo.physical_id_ << std::endl;std::cout << "Siblings: " << cpuInfo.siblings_ << std::endl;std::cout << "Core ID: " << cpuInfo.core_id_ << std::endl;std::cout << "CPU Cores: " << cpuInfo.cpu_cores_ << std::endl;std::cout << "clflush size: " << cpuInfo.clflush_size_ << std::endl;std::cout << "-------------------------" << std::endl;}std::cout << "*************************CPU信息*************************" << std::endl;std::cout << "*************************磁盘信息*************************" << std::endl;std::vector<DiskStatsInfo> disk_infos;info.GetDiskStatsAllInfo(disk_infos);for (const auto& diskStats : disk_infos) {std::cout << "-------------------------" << std::endl;std::cout << "主设备号: " << diskStats.major_device_num_ << std::endl;std::cout << "次设备号: " << diskStats.minor_device_num_ << std::endl;std::cout << "磁盘名称: " << diskStats.device_name_ << std::endl;std::cout << "完成的读操作次数: " << diskStats.read_completed_ << std::endl;std::cout << "合并读操作次数: " << diskStats.read_merged_ << std::endl;std::cout << "读取的扇区总数: " << diskStats.read_sectors_ << std::endl;std::cout << "花费在读操作上的时间: " << diskStats.read_time_spent_ << std::endl;std::cout << "完成的写操作次数: " << diskStats.write_completed_ << std::endl;std::cout << "合并写操作次数: " << diskStats.write_merged_ << std::endl;std::cout << "写入的扇区总数: " << diskStats.write_sectors_ << std::endl;std::cout << "花费在写操作上的时间: " << diskStats.write_time_spent_ << std::endl;std::cout << "-------------------------" << std::endl;}std::cout << "*************************磁盘信息*************************" << std::endl;std::cout << "*************************BIOS信息*************************" << std::endl;BIOSMoreInfo bios_info;info.GetBIOSAllInfo(bios_info);std::cout << "BIOS版本号: " << bios_info.version_ << std::endl;std::cout << "BIOS供应商: " << bios_info.vendor_ << std::endl;std::cout << "BIOS发布日期: " << bios_info.date_ << std::endl;std::cout << "BIOS 在内存中的物理地址: " << bios_info.address_ << std::endl;std::cout << "BIOS运行时占用的内存大小: " << bios_info.runtime_size_ << std::endl;std::cout << "存储BIOS固件的ROM(只读存储器)容量: " << bios_info.rom_size_ << std::endl;std::cout << "BIOS 的修订版本号: " << bios_info.bios_revision_ << std::endl;std::cout << "主板固件的版本号: " << bios_info.firmware_revisioin_ << std::endl;std::cout << "*************************BIOS信息*************************" << std::endl;std::cout << "*************************主板信息*************************" << std::endl;BaseboardMoreInfo board_info;info.GetBoardAllInfo(board_info);std::cout << "主板版本号: " << board_info.version_ << std::endl;std::cout << "主板供应商: " << board_info.vendor_ << std::endl;std::cout << "主板型号: " << board_info.name_ << std::endl;std::cout << "主板序列号: " << board_info.serial_num_ << std::endl;std::cout << "主板资产标签: " << board_info.asset_tag_ << std::endl;std::cout << "主板在机箱中的位置: " << board_info.location_in_chassis_ << std::endl;std::cout << "主板类型: " << board_info.type_ << std::endl;std::cout << "*************************主板信息*************************" << std::endl;return 0;
}

代码链接

代码地址

部分运行结果

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/902059.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BootStrap:进阶使用(其二)

今天我要讲述的是在BootStrap中第二篇关于进一步使用的方法与代码举例; 分页&#xff1a; 对于一些大型网站而言&#xff0c;分页是一个很有必要的存在&#xff0c;如果当数据内容过大时&#xff0c;则需要分页来分担一些&#xff0c;这可以使得大量内容能整合并全面地展示&a…

【技术派后端篇】技术派中的白名单机制:基于Redis的Set实现

在技术派社区中&#xff0c;为了保证文章的质量和社区的良性发展&#xff0c;所有发布的文章都需要经过审核。然而&#xff0c;并非所有作者的文章都需要审核&#xff0c;我们通过白名单机制来优化这一流程。本文将详细介绍技术派中白名单的实现方式&#xff0c;以及如何利用Re…

TRAE.AI 国际版本

国际版下载地址&#xff1a; https://www.trae.ai/https://www.trae.ai/ 国际版本优势&#xff1a;提供更多高校的AI助手模型 Claude-3.5-Sonnet Claude-3.7-Sonnet Gemini-2.5-Pro GPT-4.1 GPT-40 DeepSeek-V3-0324DeepSeek-V3DeepSeek-Reasoner(R1)

关于支付宝网页提示非官方网页

关于支付宝网站提示 非官方网站 需要找官方添加白名单 下面可以直接用自己的邮箱去发送申请 支付宝提示“非支付宝官方网页&#xff0c;请确认是否继续访问”通常是因为支付宝的安全机制检测到您访问的页面不是支付宝官方页面&#xff0c;这可能是由于域名或页面内容不符合支…

【今日三题】打怪(模拟) / 字符串分类(字符串哈希) / 城市群数量(dfs)

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;每日两三题 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 打怪(模拟)字符串分类(字符串哈希)城市群数量(dfs) 打怪(模拟) 打怪 #include <iostream> using namespace std;int …

npm install 版本过高引发错误,请添加 --legacy-peer-deps

起因&#xff1a;由于使用"react": "^19.0.0", 第三方包要低版本react&#xff0c;错解决方法&#xff01; npm install --save emoji-mart emoji-mart/data emoji-mart/react npm install --save emoji-mart emoji-mart/data emoji-mart/react npm err…

Python基础总结(七)之条件语句

文章目录 条件语句if一、Python中的真假二、条件语句格式2.1 if语句格式2.2 if-else语句2.3 if-elif-else语句 三、if语句嵌套 条件语句if 条件语句其实就是if语句&#xff0c;在讲解if语句之前需要知道Python中对于真假的判断。 一、Python中的真假 在Python中非0的都为真&…

基于Ubuntu2504部署OpenStack E版

OpenStack 初始化环境安装数据库、memcahe、rabbitmq等服务安装keystone服务安装glance服务安装placement服务安装nova服务安装neutron服务安装horizon服务 官网 OpenStack Epoxy 巩固了作为 VMware 替代方案的地位&#xff0c;增强了安全性&#xff0c;并改进了硬件支持 第 3…

可发1区的超级创新思路(python 、MATLAB实现):基于多尺度注意力TCN-KAN与小波变换的时间序列预测模型

一、数学模型与原理 1.1 小波变换多尺度分解 输入功率序列 x(t) 经小波变换分解为近似系数 Aj​ 与细节系数 Dj​: 1.2 多尺度TCN特征提取 对每个尺度子序列 {A3​,D3​,D2​,D1​} 采用独立TCN: 式中 ∗d​ 为扩张率 d=2l 的扩张卷积,Wd​ 为可学习参数。 1.3 多尺度注…

YOLOv11改进有效涨点专栏:从理论到实战的深度优化指南

## YOLOv11的进化之路 在目标检测领域,YOLO系列算法始终保持着革命性的创新步伐。YOLOv11作为该系列的最新演进版本,在保持实时检测优势的同时,通过架构层面的深度优化实现了精度与速度的平衡。本文将从**七大核心模块**出发,系统性地解析针对YOLOv11的有效改进方案,涵盖从…

Cursor新版0.49.x发布

小子看到 Cursor 0.49.x 版本正式发布&#xff0c;截止今天已经有两个小patch版本&#xff01;本次更新聚焦于 自动化Rules生成、改进的 Agent Terminal 以及 MCP 图像支持&#xff0c;并带来了一系列旨在提升编码效率和协作能力的改进与修复。 以下是本次更新的详细内容&…

《手环表带保养全攻略:材质、清洁与化学品避坑指南》

系列文章目录 文章目录 系列文章目录前言一、表带材质特性与专属养护方案二、清洁剂使用红黑榜三、家庭清洁实验&#xff1a;化学反应警示录四、保养实践方法论总结 前言 手环作为现代生活的智能伴侣&#xff0c;表带材质选择丰富多样。从柔软亲肤的皮质到耐用耐磨的金属&…

实现批量图片文字识别(python+flask+EasyOCR)

话不多说,向上效果图 1)先说框架版本 为什么要先说框架版本呢,因为我在各种版本中尝试了两天,总算确定了如下版本适合我,至于其他的版本,各位自己去尝试 python 3.9.7 EasyOCR 1.7.2 flask 3.0.3 2)执行操作效果图 2.1)多选文件 2.2)图片预览 2.3)提取选中文件 2.4)提取所有文…

国产GPU生态现状评估:从寒武纪到壁仞的编程适配挑战

近年来&#xff0c;国产GPU厂商在硬件性能上持续突破&#xff0c;但软件生态的构建仍面临严峻挑战。本文以寒武纪、壁仞等代表性企业为例&#xff0c;对比分析其与CUDA生态的兼容性差异&#xff0c;并探讨技术突围路径。 一、编程适配的核心挑战 ‌编程模型差异与开发成本‌ …

YOLOv8 Bug 及解决方案汇总 【2024.1.24更新】【环境安装】【训练 断点续训】OMPError / KeyError

YOLOv8 Bug 及解决方案汇总&#xff1a;深入解析与应对 引言 YOLOv8作为一款高性能的目标检测算法&#xff0c;在实际应用中难免会遇到各种各样的问题。本文将对YOLOv8常见的Bug进行汇总&#xff0c;并提供相应的解决方案&#xff0c;旨在帮助开发者更好地使用和优化YOLOv8。…

面试算法高频08-动态规划-02

动态规划练习题 题目描述 给定两个字符串 text1 和 text2&#xff0c;要求返回这两个字符串的最长公共子序列。例如对于字符串 “ABAZDC” 和 “BACBAD”&#xff0c;需找出它们最长的公共子序列。子序列是指在不改变其余字符相对位置的情况下&#xff0c;从原始字符串中删除…

【人工智能学习-01-01】20250419《数字图像处理》复习材料的word合并PDF,添加页码

前情提要 20250419今天是上师大继续教育人工智能专升本第一学期的第一次线下课。 三位老师把视频课的内容提炼重点再面授。&#xff08;我先看了一遍视频&#xff0c;但是算法和图像都看不懂&#xff0c;后来就直接挂分刷满时间&#xff0c;不看了&#xff09; 今天是面对面授…

AI写代码工具分享:Cursor 高效使用攻略与实战秘籍

写在前面 在软件开发领域,效率和生产力是永恒的追求。集成开发环境(IDE)作为开发者的核心工具,其能力直接影响着开发速度和质量。近年来,人工智能(AI)的浪潮席卷了各个行业,编程领域也不例外。Cursor IDE 正是这股浪潮中的佼佼者,它以 AI-First 的理念,在广受欢迎的…

守护进程编程

守护进程编程 守护进程的含义 定义 守护进程&#xff08;Daemon Process&#xff09;是在后台运行的进程&#xff0c;它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进程&#xff0c;它在系统后台运行&#xff0c;为系统或其他…

在复杂性的迷宫里寻找路标 —— 读《人月神话》有感

初读《人月神话》时&#xff0c;正值参与的第一个大型项目陷入泥潭&#xff1a;需求像不断膨胀的气球&#xff0c;团队规模从 10 人扩充到 30 人&#xff0c;进度却像被灌了铅的钟表&#xff0c;指针越来越沉重。布鲁克斯在书中写下的 "向进度落后的项目增加人力&#xff…