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.pswp.cn/news/902059.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/902059.shtml
英文地址,請注明出處:http://en.pswp.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…