C++ 無統一跨平台標準庫獲取硬件信息,需調用平台原生 API 或解析系統文件。本文匯總 Windows (註冊表、WMI、CPUID) 與 Linux (/proc、sysfs、lscpu) 的主流方案,附關鍵代碼片段。
路徑:HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\ProcessorNameString
#include <windows.h>
#include <iostream>
#include <string>
std::string getCpuNameFromRegistry() {
HKEY hKey;
char value[256];
DWORD bufSize = sizeof(value);
LONG ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey);
if (ret == ERROR_SUCCESS) {
RegQueryValueExA(hKey, "ProcessorNameString", nullptr, nullptr, (LPBYTE)value, &bufSize);
RegCloseKey(hKey);
return std::string(value);
}
return "Unknown";
}
可查詢 CPU、磁盤、內存、主板、BIOS 等所有信息。需鏈接 wbemuuid.lib,代碼較繁瑣,建議封裝工具類。核心步驟:CoInitialize → CoCreateInstance(CLSID_WbemLocator) → ConnectServer → ExecQuery("SELECT * FROM Win32_Processor") → 遍歷 IEnumWbemClassObject。
#include <array>
#include <string>
std::string getCpuBrandString() {
std::array cpui;
char brand[48] = {0};
// 调用 CPUID leaf 0x80000002~0x80000004
for (unsigned int i = 0x80000002; i <= 0x80000004; ++i) {
__cpuid(cpui.data(), i);
*reinterpret_cast(brand + (i - 0x80000002) * 16) = cpui[0];
*reinterpret_cast(brand + (i - 0x80000002) * 16 + 4) = cpui[1];
*reinterpret_cast(brand + (i - 0x80000002) * 16 + 8) = cpui[2];
*reinterpret_cast(brand + (i - 0x80000002) * 16 + 12) = cpui[3];
}
return std::string(brand);
}
/proc/cpuinfo (CPU 詳細信息)#include <fstream>
#include <sstream>
#include <unordered_map>
std::unordered_map parseCpuinfo() {
std::ifstream file("/proc/cpuinfo");
std::unordered_map info;
std::string line;
while (std::getline(file, line)) {
size_t pos = line.find(':');
if (pos != std::string::npos) {
std::string key = line.substr(0, pos);
std::string val = line.substr(pos + 1);
// 只保留第一個 processor 的信息
if (info.find(key) == info.end()) info[key] = val;
}
}
return info;
}
// 使用: auto info = parseCpuinfo(); std::cout << info["model name"];
/proc/meminfo (內存大小)long long getTotalMemKb() {
std::ifstream file("/proc/meminfo");
std::string line;
while (std::getline(file, line)) {
if (line.rfind("MemTotal:", 0) == 0) {
std::istringstream iss(line);
std::string label; long long kb;
iss >> label >> kb;
return kb; // 單位 KB
}
}
return -1;
}
statvfs 獲取磁盤空間#include <sys/statvfs.h>
struct DiskSpace { unsigned long long total, free, available; };
DiskSpace getDiskSpace(const char* path = "/") {
struct statvfs st;
if (statvfs(path, &st) == 0) {
return { st.f_blocks * st.f_frsize,
st.f_bfree * st.f_frsize,
st.f_bavail * st.f_frsize };
}
return {0,0,0};
}
調用 popen("lscpu -J", "r") 解析 JSON 輸出 (需系統安裝 util-linux),適合快速開發、不想手寫解析器的場景。
SystemInfo 接口,編譯期根據 `_WIN32` / `__linux__` 切換實現。systeminfo 或 wmic 解析文本輸出:版本差異大、本地化語言導致解析失敗、性能差。| 信息類型 | Windows 首選 | Linux 首選 |
|---|---|---|
| CPU 型號/名稱 | 註冊表 / WMI / CPUID | /proc/cpuinfo / lscpu |
| 邏輯核心數 | GetLogicalProcessorInformation | nproc / /proc/cpuinfo 統計 processor |
| 物理內存大小 | GlobalMemoryStatusEx / WMI | /proc/meminfo (MemTotal) |
| 磁盤總/可用空間 | GetDiskFreeSpaceEx / WMI | statvfs / df / lsblk |
| 主板/BIOS 信息 | WMI (Win32_BaseBoard) | dmidecode (需 root) / /sys/class/dmi/id/ |
根據項目約束 (是否能引入第三方庫、是否需跨平台、權限要求) 選擇合適方案。註冊表/系統文件解析無需特殊權限,WMI/dmidecode 可能需管理員/root 權限。