Linux下如何使用C++獲取硬件信息
方法
通過讀取Linux下存放硬件信息的文件來獲取CPU、主板、磁盤、BIOS信息
獲取CPU信息:讀取"/proc/cpuinfo"文件
字段及其含義:
處理器基本信息:
- processor:處理器的邏輯編號(hào),從 0 開始,用于標(biāo)識(shí)系統(tǒng)中的每個(gè)邏輯 CPU。
- vendor_id:CPU制造商的標(biāo)識(shí)符。例如,對于 Intel CPU,可能是GenuineIntel;對于 AMD CPU,可能是AuthenticAMD。
處理器型號(hào)與家族信息
- cpu family:CPU 所屬的家族編號(hào)。不同家族的 CPU 可能具有不同的架構(gòu)和特性。例如,Intel 的酷睿系列和至強(qiáng)系列可能屬于不同的家族。
- model:CPU型號(hào)編號(hào),結(jié)合cpu family可以更準(zhǔn)確地確定 CPU 的具體型號(hào)。
- model name:CPU 的完整型號(hào)名稱,提供了詳細(xì)的 CPU 型號(hào)描述,如Intel® Core™ i7-10700K CPU @ 3.80GHz。
步進(jìn)與微代碼信息:
- stepping:CPU的步進(jìn)編號(hào),它標(biāo)識(shí)了 CPU 的修訂版本。不同的步進(jìn)可能包含對之前版本的錯(cuò)誤修復(fù)或性能改進(jìn)。
- microcode:CPU微代碼版本號(hào),微代碼是嵌入在 CPU 中的一小段代碼,用于協(xié)助 CPU 執(zhí)行指令,可以通過更新微代碼來修復(fù) CPU 的一些問題或提升性能。
性能相關(guān)信息:
cpu MHz:CPU當(dāng)前的運(yùn)行頻率,單位為 MHz。這可能是動(dòng)態(tài)變化的,尤其是在支持節(jié)能技術(shù)(如 Intel 的 SpeedStep 或 AMD 的
- Cool’n’Quiet)的 CPU 上。
- cache size:CPU 緩存的大小,通常以 KB 或 MB 為單位。緩存可以提高 CPU 訪問數(shù)據(jù)的速度,較大的緩存通常意味著更好的性能。
多處理器與多核信息:
- physical id:物理處理器的標(biāo)識(shí)符。在多處理器系統(tǒng)中,每個(gè)物理 CPU 有一個(gè)唯一的physical id。
- siblings:同一物理 CPU上的邏輯處理器數(shù)量,即超線程技術(shù)下每個(gè)物理核心對應(yīng)的邏輯核心數(shù)。例如,如果一個(gè)物理核心支持超線程,siblings可能為 2。
- core id:每個(gè)物理核心的唯一標(biāo)識(shí)符,在同一物理 CPU 內(nèi),不同的物理核心有不同的core id。
- cpu cores:每個(gè)物理 CPU 中的核心數(shù)量,不包括超線程產(chǎn)生的邏輯核心。
其他信息:
- apicid:高級可編程中斷控制器(APIC)標(biāo)識(shí)符,用于多處理器系統(tǒng)中的中斷處理。
- flags:CPU支持的特性標(biāo)志列表,每個(gè)標(biāo)志表示 CPU 支持的一種特定功能或指令集,如mmx、sse、sse2等,這些指令集可以加速特定類型的計(jì)算任務(wù)。
- bogomips:代表 “BogusMIPS(偽每秒百萬條指令數(shù))”。它是一種對 CPU 性能的近似估計(jì)值,并非基于實(shí)際指令執(zhí)行的精確測量。這個(gè)數(shù)值最初由 Linus Torvalds引入 Linux 內(nèi)核,作為一種快速且相對簡單的方法來評估 CPU 的處理能力。
- clflush size:緩存行刷新(Cache Line Flush)操作所涉及的緩存行大小。
獲取磁盤信息:讀取"/proc/diskstats"文件
字段及其含義(從左至右):
- 主設(shè)備號(hào)(Major device number):在示例中為8,它標(biāo)識(shí)設(shè)備類型。例如,8通常代表SCSI 磁盤設(shè)備。不同的設(shè)備類型有不同的主設(shè)備號(hào),可用于識(shí)別設(shè)備所屬的大類。
- 次設(shè)備號(hào)(Minor device number):示例中的0,它用于在同一主設(shè)備類型下進(jìn)一步區(qū)分具體的設(shè)備實(shí)例。主設(shè)備號(hào)和次設(shè)備號(hào)共同唯一標(biāo)識(shí)系統(tǒng)中的一個(gè)塊設(shè)備。
- 設(shè)備名稱(Device name):這里是sda,這是設(shè)備在系統(tǒng)中的名稱,通常對應(yīng)/dev目錄下的設(shè)備文件名,方便用戶和系統(tǒng)管理員識(shí)別和操作具體設(shè)備。
- 讀完成次數(shù)(Reads completed successfully):212553,表示從設(shè)備成功完成的讀操作次數(shù)。每次成功讀取數(shù)據(jù)塊,該計(jì)數(shù)增加。
- 讀合并次數(shù)(Reads merged):14992,系統(tǒng)有時(shí)會(huì)合并相鄰的讀請求以提高 I/O 效率,該字段統(tǒng)計(jì)了合并讀操作的次數(shù)。合并讀可以減少I/O 操作的總次數(shù),提升性能。
- 讀扇區(qū)數(shù)(Sectors read):1469963,表示從設(shè)備讀取的扇區(qū)總數(shù)。一個(gè)扇區(qū)通常是 512 字節(jié)(在現(xiàn)代設(shè)備中也可能是 4096字節(jié)等),這個(gè)數(shù)字反映了讀取的數(shù)據(jù)量(以扇區(qū)為單位)。
- 讀操作花費(fèi)的毫秒數(shù)(Time spent reading (ms)):334512,累計(jì)花費(fèi)在讀操作上的時(shí)間,以毫秒為單位。它反映了設(shè)備讀取數(shù)據(jù)所花費(fèi)的總時(shí)間,可用于評估讀性能。
- 寫完成次數(shù)(Writes completed successfully):1005650,表示向設(shè)備成功完成的寫操作次數(shù)。每次成功寫入數(shù)據(jù)塊,該計(jì)數(shù)增加。
- 寫合并次數(shù)(Writes merged):121259,類似于讀合并,系統(tǒng)會(huì)合并相鄰的寫請求,該字段統(tǒng)計(jì)了合并寫操作的次數(shù),以提高寫性能。
- 寫扇區(qū)數(shù)(Sectors written):6743707,表示向設(shè)備寫入的扇區(qū)總數(shù),反映了寫入的數(shù)據(jù)量(以扇區(qū)為單位)。
- 寫操作花費(fèi)的毫秒數(shù)(Time spent writing (ms)):10052256,累計(jì)花費(fèi)在寫操作上的時(shí)間,以毫秒為單位,可用于評估寫性能。
- 當(dāng)前I/O 操作數(shù)(I/O requests currently in progress):0,表示當(dāng)前正在進(jìn)行的 I/O請求數(shù)量。如果這個(gè)值持續(xù)不為零,可能表示設(shè)備出現(xiàn)了 I/O 瓶頸。
- I/O操作花費(fèi)的總毫秒數(shù)(Time spent doing I/O (ms)):343049,累計(jì)花費(fèi)在所有 I/O操作(讀和寫)上的時(shí)間,以毫秒為單位。
- 加權(quán)的I/O 操作花費(fèi)的毫秒數(shù)(Weighted time spent doing I/O (ms)):10386768,這是一個(gè)加權(quán)時(shí)間,考慮了I/O 請求的排隊(duì)時(shí)間等因素,能更全面地反映 I/O 操作對系統(tǒng)資源的占用情況。
獲取BIOS信息有兩種方法
1.讀取文件
可以通過讀取三個(gè)文件分別獲得BIOS供應(yīng)商名稱、BIOS版本號(hào)、BIOS發(fā)布日期,分別是:
BIOS供應(yīng)商名稱:/sys/class/dmi/id/bios_vendor
BIOS版本號(hào):/sys/class/dmi/id/bios_version
BIOS發(fā)布日期:/sys/class/dmi/id/bios_date
優(yōu)點(diǎn):
無需 root 權(quán)限??:普通用戶即可訪問。無額外依賴??:直接通過文件接口讀取,避免調(diào)用外部命令。??適用于容器/虛擬化環(huán)境??:即使 DMI 信息被限制,部分字段仍可能可用。
缺點(diǎn):獲取到的信息少。
2.使用dmidecode命令
工作方式:dmidecode的工作方式就是解析DMI表
命令:sudo dmidecode -t bios
字段含義:
- Vendor:BIOS供應(yīng)商名稱
- Version:BIOS版本號(hào)
- Release Date:BIOS發(fā)布日期
- Address:BIOS在內(nèi)存中的物理地址(十六進(jìn)制)
- Runtime Size?:BIOS運(yùn)行時(shí)占用的內(nèi)存大小
- ROM Size:存儲(chǔ) BIOS固件的 ROM(只讀存儲(chǔ)器)容量
- Characteristics:BIOS支持的特性列表,每個(gè)特性對應(yīng)一個(gè)硬件或軟件功能
- ??BIOS Revision?:BIOS 的修訂版本號(hào)(可能與 Version 不同)
- Firmware Revision?:主板固件的版本號(hào)(可能與 BIOS 版本分離)
優(yōu)點(diǎn): 獲取的信息更多、更全面。
缺點(diǎn):?
- 權(quán)限要求??:dmidecode 需要 ??root 權(quán)限?? 才能讀取完整 DMI表,如果運(yùn)行程序的用戶不是root用戶會(huì)失敗。
- 依賴性??:dmidecode方法需要安裝該工具(通常默認(rèn)已安裝),常見的安裝目錄。有"/usr/sbin/dmidecode"、“/sbin/dmidecode”、“/usr/local/sbin/dmidecode”。代碼在調(diào)用命令前需要先驗(yàn)證是否存在路徑。
- 適用性??:虛擬化環(huán)境(如容器)中可能無法提供完整的DMI信息。
獲取主板信息有兩種方法
1.讀取文件
可以通過讀取文件分別獲得主板供應(yīng)商名稱、主板版本號(hào)、主板型號(hào),主板序列號(hào),主板資產(chǎn)標(biāo)簽分別是:
主板供應(yīng)商名稱:/sys/class/dmi/id/board_vendor
主板版本號(hào):/sys/class/dmi/id/board_version
主板型號(hào):/sys/class/dmi/id/board_name
主板序列號(hào):/sys/class/dmi/id/board_serial,讀取該文件需要root權(quán)限,所以代碼中無法依靠讀取文件獲取,但是可以通過dmidecode命令獲?。ㄒ娤挛模?/p>
主板資產(chǎn)標(biāo)簽:/sys/class/dmi/id/board_asset_tag
優(yōu)點(diǎn):
無需 root 權(quán)限??:普通用戶即可訪問。無額外依賴??:直接通過文件接口讀取,避免調(diào)用外部命令。??適用于容器/虛擬化環(huán)境??:即使 DMI 信息被限制,部分字段仍可能可用。
缺點(diǎn): 獲取到的信息少。
2.使用dmidecode命令
工作方式:dmidecode的工作方式就是解析DMI表
命令:sudo dmidecode -t baseboard
字段含義:
- Manufacturer:主板制造商
- Product Name: 主板型號(hào)
- Version:主板版本號(hào),None為未指定
- Serial Number:主板序列號(hào),None為未指定
- Asset Tag: 資產(chǎn)標(biāo)簽,Not Specified為未指定
- Features:主板特殊功能,None為無特殊功能
- Location In Chassis:主板在機(jī)箱中的位置,Not Specified未記錄
- Chassis Handle:關(guān)聯(lián)的機(jī)箱記錄句柄,0x0000為未關(guān)聯(lián)或默認(rèn)值
- Type:主板類型,Unknown為未明確
- Contained Object Handle:關(guān)聯(lián)的子設(shè)備,0表示無關(guān)聯(lián)
優(yōu)點(diǎn): 獲取的信息更多、更全面。
缺點(diǎn):?
- 權(quán)限要求??:dmidecode 需要 ??root 權(quán)限?? 才能讀取完整 DMI表,如果運(yùn)行程序的用戶不是root用戶會(huì)失敗。
- 依賴性??:dmidecode方法需要安裝該工具(通常默認(rèn)已安裝),常見的安裝目錄。有"/usr/sbin/dmidecode"、“/sbin/dmidecode”、“/usr/local/sbin/dmidecode”。代碼在調(diào)用命令前需要先驗(yàn)證是否存在路徑。
- 適用性??:虛擬化環(huán)境(如容器)中可能無法提供完整的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信息結(jié)構(gòu)體 struct CPUInfo { std::string processor_; // CPU 的邏輯編號(hào) std::string vendor_id_; // CPU 制造商的標(biāo)識(shí)符 std::string cpu_family_; // CPU 所屬的家族編號(hào) std::string model_; // CPU 型號(hào)編號(hào) std::string model_name_; // CPU 的完整型號(hào)名稱 std::string stepping_; // CPU 的步進(jìn)編號(hào) std::string microcode_; // CPU 微代碼版本號(hào) std::string cpu_freq_; // CPU 當(dāng)前的運(yùn)行頻率,單位為 MHz std::string cache_size_; // CPU 緩存的大小,單位為KB std::string physical_id_; // CPU 的標(biāo)識(shí)符 std::string siblings_; // 同一物理 CPU 上的邏輯處理器數(shù)量 std::string core_id_; // 每個(gè)物理核心的唯一標(biāo)識(shí)符 std::string cpu_cores_; // 每個(gè)物理 CPU 中的核心數(shù)量,不包括超線程產(chǎn)生的邏輯核心 std::string clflush_size_; // 緩存行刷新(Cache Line Flush)操作所涉及的緩存行大小 }; // 磁盤信息結(jié)構(gòu)體 struct DiskStatsInfo { std::string major_device_num_; // 主設(shè)備號(hào),標(biāo)識(shí)設(shè)備類型 std::string minor_device_num_; // 次設(shè)備號(hào),用于在同一主設(shè)備類型下進(jìn)一步區(qū)分具體的設(shè)備實(shí)例,主設(shè)備號(hào)和次設(shè)備號(hào)共同唯一標(biāo)識(shí)系統(tǒng)中的一個(gè)塊設(shè)備 std::string device_name_; // 磁盤名稱,對應(yīng)/dev目錄下的設(shè)備文件名 std::string read_completed_; // 從設(shè)備成功完成的讀操作次數(shù),每次成功讀取數(shù)據(jù)塊,該計(jì)數(shù)增加 std::string read_merged_; // 合并讀操作次數(shù) std::string read_sectors_; // 從設(shè)備讀取的扇區(qū)總數(shù) std::string read_time_spent_; // 累計(jì)花費(fèi)在讀操作上的時(shí)間,單位毫秒 std::string write_completed_; // 向設(shè)備成功完成的寫操作次數(shù),每次成功寫入數(shù)據(jù)塊,該計(jì)數(shù)增加 std::string write_merged_; // 合并寫操作次數(shù) std::string write_sectors_; // 向設(shè)備寫入的扇區(qū)總數(shù) std::string write_time_spent_; // 累計(jì)花費(fèi)在寫操作上的時(shí)間,單位毫秒 }; // BIOS信息結(jié)構(gòu)體,細(xì)節(jié)信息通過dmidecode命令獲取到的 struct BIOSMoreInfo { // 基礎(chǔ)信息 std::string vendor_; // BIOS供應(yīng)商 std::string version_; // BIOS版本 std::string date_; // BIOS發(fā)布日期 // 細(xì)節(jié)信息 std::string address_; // BIOS 在內(nèi)存中的物理地址(十六進(jìn)制) std::string runtime_size_; // BIOS運(yùn)行時(shí)占用的內(nèi)存大小,單位為bytes std::string rom_size_; // 存儲(chǔ) BIOS 固件的 ROM(只讀存儲(chǔ)器)容量,單位為kB std::string bios_revision_; // BIOS的修訂版本號(hào),可能與Version不同 std::string firmware_revisioin_; // 主板固件版本號(hào) }; // 主板信息結(jié)構(gòu)體,細(xì)節(jié)信息通過dmidecode命令獲取 struct BaseboardMoreInfo { // 基礎(chǔ)信息 std::string vendor_; // 主板供應(yīng)商 std::string version_; // 主板版本號(hào) std::string name_; // 主板型號(hào) std::string asset_tag_; // 主板資產(chǎn)標(biāo)簽 // 細(xì)節(jié)信息 std::string serial_num_; // 主板序列號(hào) std::string location_in_chassis_; // 主板在機(jī)箱中的位置 std::string type_; // 主板類型 }; // 檢測當(dāng)前運(yùn)行環(huán)境是否可以使用dmidecode命令 #ifndef IsUseDmidecodeCommand #define IsUseDmidecodeCommand()\ bool is_use_dmidecode = false;\ \ if(geteuid() == 0 && FindDmidecodePath())\ is_use_dmidecode = true;\ else\ std::cout << "當(dāng)前運(yùn)行環(huán)境不支持dmidecode命令, 只獲取基本信息" << std::endl; #endif // 根據(jù):進(jìn)行字符串切割并去除兩端空格得到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 會(huì)有多個(gè)cpu的信息 */ void GetProcessorAllInfo(std::vector<CPUInfo>& _cpu_infos); /* @brief 獲取磁盤的所有信息 @param _disk_infos 會(huì)有多個(gè)磁盤信息 */ void GetDiskStatsAllInfo(std::vector<DiskStatsInfo>& _disk_infos); /* @brief 獲取BIOS的信息 1、該接口會(huì)先使用demidecode命令獲取BIOS更詳細(xì)的信息,如果檢測到系統(tǒng)的demidecode命令無法使用,改用讀取文件的方式只獲取BISO 基本信息!?。? 2、該接口返回true的情況為:Linux系統(tǒng)已經(jīng)安裝demidecode命令,并且運(yùn)行程序的用戶為root用戶 @param _bios_info BIOS信息結(jié)構(gòu)體 @return true表示demidecode命令可以使用,獲取到了更詳細(xì)的信息;false說明當(dāng)前運(yùn)行環(huán)境的demidecode命令無法使用,只能獲取基本信息。 */ bool GetBIOSAllInfo(BIOSMoreInfo& _bios_info); /* @brief 獲取主板的信息 1、該接口會(huì)先使用demidecode命令獲取BIOS更詳細(xì)的信息,如果檢測到系統(tǒng)的demidecode命令無法使用,改用讀取文件的方式只獲取主板 基本信息?。?! 2、該接口返回true的情況為:Linux系統(tǒng)已經(jīng)安裝demidecode命令,并且運(yùn)行程序的用戶為root用戶 @param _board_info 主板信息結(jié)構(gòu)體 @return true表示demidecode命令可以使用,獲取到了更詳細(xì)的信息;false說明當(dāng)前運(yùn)行環(huán)境的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 存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)體 */ void ParseProcessorLine(const std::string& _line, CPUInfo& _cpu_info); /* @brief 處理BISO信息的一行 @param _line 一行字符串 @param _bios_info BISO數(shù)據(jù)結(jié)構(gòu)體 */ void ProcessBIOSLine(const std::string& _line, BIOSMoreInfo& _bios_info); /* @brief 處理主板信息的一行 @param _line 一行字符串 @param _board_info 主板數(shù)據(jù)結(jié)構(gòu)體 */ void ProcessBoardLine(const std::string& _line, BaseboardMoreInfo& _board_info); /* @brief 檢查 dmidecode 是否存在并返回其完整路徑 @return true表示存在,false表示不存在 */ bool FindDmidecodePath(); /* @brief 執(zhí)行命令并捕獲輸出 @param cmd 命令 @return 輸出的字符串 */ std::string GetStrByCommand(const char* _cmd); /* @brief 按照換行符進(jìn)行切割 @param _str 源字符串 @return 切割后的集合 */ std::vector<std::string> SplitByNewline(const std::string& _str); /* @brief 更新主板結(jié)構(gòu)體處理器 @param _key 結(jié)構(gòu)體成員對應(yīng)的key值 @param value 結(jié)構(gòu)體成員值 */ void UpdateBoardInfo(BaseboardMoreInfo& _board_info, const std::string& _key, const std::string& _value); /* @brief 更新BIOS結(jié)構(gòu)體處理器 @param _key 結(jié)構(gòu)體成員對應(yīng)的key值 @param value 結(jié)構(gòu)體成員值 */ void UpdateBIOSInfo(BIOSMoreInfo& _bios_info, const std::string& _key, const std::string& _value); /* @brief 更新CPU結(jié)構(gòu)體處理器 @param _key 結(jié)構(gòu)體成員對應(yīng)的key值 @param value 結(jié)構(gòu)體成員值 */ 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系統(tǒng)下cpu信息的存儲(chǔ)路徑 const std::string disk_file_; // Linux系統(tǒng)下磁盤信息的存儲(chǔ)路徑 const std::string bios_dir_; // Linux系統(tǒng)下存放BIOS信息的目錄 const std::vector<std::string> bios_files_name_; // Linux系統(tǒng)下存放BIOS信息的所有文件名 const std::string board_dir_; // Linux系統(tǒng)下存放主板信息的目錄 const std::vector<std::string> board_files_name_; // Linux系統(tǒng)下存放主板信息的所有文件名 const std::vector<std::string> dmidecode_command_path_; // Linux系統(tǒng)下常見的demidecode命令的完整路徑,檢測系統(tǒng)是否安裝該命令會(huì)用到 std::unordered_map<std::string, std::function<void(std::string)>> process_board_value_map_; // 給主板信息結(jié)構(gòu)體賦值 };
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()) { // 讀取下一個(gè)cpu的信息 if(!cpuInfo.model_name_.empty()) { _cpu_info.push_back(cpuInfo); cpuInfo = CPUInfo(); } } else ParseProcessorLine(line, cpuInfo); } // 添加最后一個(gè)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命令獲取更詳細(xì)的BISO信息 { try { // 對獲取到的命令輸出進(jìn)行字符串切割 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命令執(zhí)行錯(cuò)誤: " << 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命令獲取更詳細(xì)的主板信息 { try { // 對獲取到的命令輸出進(jìn)行字符串切割 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命令執(zhí)行錯(cuò)誤: " << 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方法判斷空白字符,因?yàn)闀?huì)有\(zhòng)t等情況 if(!head_flag && std::isspace(_str[head_idx])) head_idx++; else head_flag = true; if(!tail_flag && std::isspace(_str[tail_idx])) tail_idx--; else tail_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 << "主設(shè)備號(hào): " << diskStats.major_device_num_ << std::endl; std::cout << "次設(shè)備號(hào): " << diskStats.minor_device_num_ << std::endl; std::cout << "磁盤名稱: " << diskStats.device_name_ << std::endl; std::cout << "完成的讀操作次數(shù): " << diskStats.read_completed_ << std::endl; std::cout << "合并讀操作次數(shù): " << diskStats.read_merged_ << std::endl; std::cout << "讀取的扇區(qū)總數(shù): " << diskStats.read_sectors_ << std::endl; std::cout << "花費(fèi)在讀操作上的時(shí)間: " << diskStats.read_time_spent_ << std::endl; std::cout << "完成的寫操作次數(shù): " << diskStats.write_completed_ << std::endl; std::cout << "合并寫操作次數(shù): " << diskStats.write_merged_ << std::endl; std::cout << "寫入的扇區(qū)總數(shù): " << diskStats.write_sectors_ << std::endl; std::cout << "花費(fèi)在寫操作上的時(shí)間: " << 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版本號(hào): " << bios_info.version_ << std::endl; std::cout << "BIOS供應(yīng)商: " << bios_info.vendor_ << std::endl; std::cout << "BIOS發(fā)布日期: " << bios_info.date_ << std::endl; std::cout << "BIOS 在內(nèi)存中的物理地址: " << bios_info.address_ << std::endl; std::cout << "BIOS運(yùn)行時(shí)占用的內(nèi)存大小: " << bios_info.runtime_size_ << std::endl; std::cout << "存儲(chǔ)BIOS固件的ROM(只讀存儲(chǔ)器)容量: " << bios_info.rom_size_ << std::endl; std::cout << "BIOS 的修訂版本號(hào): " << bios_info.bios_revision_ << std::endl; std::cout << "主板固件的版本號(hào): " << bios_info.firmware_revisioin_ << std::endl; std::cout << "*************************BIOS信息*************************" << std::endl; std::cout << "*************************主板信息*************************" << std::endl; BaseboardMoreInfo board_info; info.GetBoardAllInfo(board_info); std::cout << "主板版本號(hào): " << board_info.version_ << std::endl; std::cout << "主板供應(yīng)商: " << board_info.vendor_ << std::endl; std::cout << "主板型號(hào): " << board_info.name_ << std::endl; std::cout << "主板序列號(hào): " << board_info.serial_num_ << std::endl; std::cout << "主板資產(chǎn)標(biāo)簽: " << board_info.asset_tag_ << std::endl; std::cout << "主板在機(jī)箱中的位置: " << board_info.location_in_chassis_ << std::endl; std::cout << "主板類型: " << board_info.type_ << std::endl; std::cout << "*************************主板信息*************************" << std::endl; return 0; }
代碼鏈接
部分運(yùn)行結(jié)果
以上就是Linux下如何使用C++獲取硬件信息的詳細(xì)內(nèi)容,更多關(guān)于C++獲取硬件信息的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言中typedef的用法以及#define區(qū)別詳解
這篇文章主要給大家介紹了關(guān)于C語言中typedef用法以及#define區(qū)別的相關(guān)資料,typedef 是用來定義一種類型的新別名的,它不同于宏(#define),不是簡單的字符串替換。而#define只是簡單的字符串替換(原地?cái)U(kuò)展),需要的朋友可以參考下2021-07-07用C語言winform編寫滲透測試工具實(shí)現(xiàn)SQL注入功能
本篇文章主要介紹使用C#winform編寫滲透測試工具,實(shí)現(xiàn)SQL注入的功能。使用python編寫SQL注入腳本,基于get顯錯(cuò)注入的方式進(jìn)行數(shù)據(jù)庫的識(shí)別、獲取表名、獲取字段名,最終獲取用戶名和密碼;使用C#winform編寫windows客戶端軟件調(diào)用.py腳本,實(shí)現(xiàn)用戶名和密碼的獲取2021-08-08C語言 數(shù)據(jù)結(jié)構(gòu)雙向鏈表簡單實(shí)例
這篇文章主要介紹了C語言 數(shù)據(jù)結(jié)構(gòu)雙向鏈表簡單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03OpenCV圖像算法實(shí)現(xiàn)圖像切分圖像合并示例
這篇文章主要為大家介紹了python圖像算法OpenCV實(shí)現(xiàn)圖像切分圖像合并操作示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06仿現(xiàn)代C++智能指針實(shí)現(xiàn)引用計(jì)數(shù)
這篇文章主要為大家詳細(xì)介紹了如何仿現(xiàn)代C++智能指針實(shí)現(xiàn)引用計(jì)數(shù),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以了解下2024-03-03