如何使用 C++ 在 Linux 中获取硬件信息

Posted

技术标签:

【中文标题】如何使用 C++ 在 Linux 中获取硬件信息【英文标题】:Howto get hardware information in Linux using C++ 【发布时间】:2011-07-08 19:04:55 【问题描述】:

我需要获取 Win 和 *nix 机器上的硬盘规格。我在 Linux 上这样使用 <hdreg.h>

   static struct hd_driveid hd;
   int device;
   if ((device = open("/dev/sda", O_RDONLY | O_NONBLOCK)) < 0)
   
      cerr << "ERROR: Cannot open device /dev/sda \n";
      exit(1);
   

   if (!ioctl(device, HDIO_GET_IDENTITY, &hd))
   
      cout << hd.model << endl;
      cout << hd.serial_no << endl;
      cout << hd.heads << endl;
   

我需要hd_driveid 告诉我有关磁盘的更多信息。我想知道:

分区数 每个分区的规格(格式、标签、标志、大小、起点、轨道数等) 每个柱面的磁道数 曲目总数 最大块大小 最小块大小 默认块大小 设备总大小

我的问题是:

    有没有共同点 (平台无关)方式 连接硬件?我想使用 win 和 *nix 的代码相同。 (即使 没有别的办法 将汇编代码嵌入 cpp) 如果没有,我如何在 *nix 中获取上述信息?

【问题讨论】:

有些系统没有分区...有些(通常在 *BSD 中)使用“切片”,而其他可能只是使用完整的硬盘驱动器。 (即未分区)。 【参考方案1】:

您列表中的几乎所有内容都与“硬盘规格”无关:

分区数取决于读取分区表,如果有任何扩展分区,这些分区的分区表。加载设备驱动程序时,操作系统通常会为您执行此操作。 分区信息(即卷标)通常在分区表中不可用。您需要猜测文件系统类型并解析文件系统标头。分区表中唯一的内容是“类型”字节,它不会告诉你太多,还有开始/大小。 硬盘驱动器不会为您提供“真实”的 CHS 信息。此外,从 Bios 的角度来看,驱动器提供的 CHS 信息是“错误的”(BIOS 会自行伪造)。 硬盘驱动器具有固定的扇区大小,您可以使用hd_driveid.sector_bytes 获得(通常为 512,但一些现代驱动器使用 4096)。我不知道最大“块大小”,这是文件系统的一个属性。我也不确定这为什么有用。

扇区的总大小为hd_driveid.lba_capacity_2。此外,字节大小可能可以通过类似的方式获得

#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
#include <unistd.h>

...
off_t size_in_bytes = lseek(device, 0, SEEK_END);
if (size_in_bytes == (off_t)-1)  ... error, error code in ERRNO ... 

请注意,在这两种情况下,它都可能比 C×H×S 计算的大小大几兆字节。

如果你告诉我们你为什么想要这些信息可能会有所帮助......

【讨论】:

谢谢 tc。我克服了T=t×S,其中 S 是 sectors,t 是轨道数。我不知道block size 是什么,除了我的老师 C# 示例之外,我在其他任何地方都找不到它。在这个例子中,有一个ManagementObject 的实例,这些信息是由字符串索引器从中提取的......(我忘了说我正在写作业:-) hd.model、hd.serial_no 等参数是真实的。有人可以给我一个提示,为什么我的 hd_driveid.sector_bytes 等于零?我只需要这个参数,它等于零... @shbk:最好开始一个新问题,准确说明您正在使用的硬件、运行的完整代码以及输出的内容。如果您解释您最终要达到的目标,也更容易提供帮助。【参考方案2】:
//-------------------------------------------------
// Without Boost LIB usage
//-------------------------------------------------
#include <sys/statvfs.h>
#include <sys/sysinfo.h>
//-------------------------------------------------
stringstream   strStream;
unsigned long  hdd_size;
unsigned long  hdd_free;
ostringstream  strConvert;
//---
struct sysinfo info;
sysinfo( &info );   
//---
struct statvfs fsinfo;
statvfs("/", &fsinfo);
//---
//---
unsigned num_cpu = std::thread::hardware_concurrency();
//---
ifstream cpu_freq("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq");
strStream << cpu_freq.rdbuf();
std::string  cpufrequency = strStream.str();
//---
strStream.str("");
ifstream cpu_temp("/sys/class/thermal/thermal_zone0/temp");
strStream << cpu_temp.rdbuf();
strConvert<< fixed << setprecision(2) << std::stof(strStream.str());
std::string cputemp = strConvert.str();
//---
std::string   mem_size = to_string( (size_t)info.totalram *     (size_t)info.mem_unit );
//---
hdd_size = fsinfo.f_frsize * fsinfo.f_blocks;
hdd_free = fsinfo.f_bsize * fsinfo.f_bfree;  
//---                                                
std::cout << "CPU core number           ==" << num_cpu       << endl;
std::cout << "CPU core speed            ==" << cpufrequency  << endl;
std::cout << "CPU temperature (C)       ==" << cputemp       << endl;
//---
std::cout << "Memory size               ==" << mem_size      << endl;
//---
std::cout << "Disk, filesystem size     ==" << hdd_size      << endl;
std::cout << "Disk free space           ==" << hdd_free      << endl;
//---

【讨论】:

【参考方案3】:

不,没有平台无关的方式。甚至没有 *nix 方式。只有 Linux 方式。

在 Linux 中,所有相关信息都可以在 /proc 文件系统中的各种文件中找到。 /proc/devices 会告诉你有哪些设备(/dev/ 中的文件即使设备不可用也可能存在,尽管在这种情况下打开它们会失败),/proc/partitions 会告诉你每个分区上有哪些可用的分区磁盘,然后您必须在各个子目录中查找信息。看看你所需要的一些 linux 系统。

【讨论】:

感谢您的回答,但我在那里找不到我需要的东西...我想知道/proc 中的文件是如何创建的?我想在我的程序中自己获取硬件信息:-)(与在/proc 中生成它们的方式相同) @Sorush proc 中的“文件”实际上是一个特殊的文件系统(称为 procfs),可以直接读取和/或写入内核。您需要深入研究 linux 内核以了解 procfs 如何获取其数据。 procfs 的全部意义在于暴露数据而无需成为内核黑客。 @Sorush:你将不得不挖很多地方来收集你需要的所有东西。不幸的是,我现在不在 Linux 系统上,我不记得确切的文件,但有类似 /proc/bus/ide/proc/bus/scsi 之类的东西,还有许多包含各种信息的文件,你需要收集。【参考方案4】:

对于 GNU/Linux,看看这个:obtaining hard disk metadata

【讨论】:

【参考方案5】:
//Piece of code working for me with Boost LIB usage
//-----------------------------------------------------
#include <sys/sysinfo.h>
#include <boost/filesystem.hpp>
//---    
using namespace boost::filesystem;
//---
struct sysinfo info;
sysinfo( &info );
//---
space_info si = space(".");
//---
unsigned num_cpu = std::thread::hardware_concurrency();
//---
ifstream  cpu_freq("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq");
ifstream cpu_temp("/sys/class/thermal/thermal_zone0/temp");
//---
std::string cpunumber = to_string(num_cpu);
std::string cpufrequency = cpu_freq.str();
std::string cputemp = cpu_temp.str();
std::string mem_size = to_string( (size_t)info.totalram *     (size_t)info.mem_unit );
std::string disk_available = to_string(si.available);
std::string fslevel = to_string( (si.available/si.capacity)*100 );
//---

【讨论】:

以上是关于如何使用 C++ 在 Linux 中获取硬件信息的主要内容,如果未能解决你的问题,请参考以下文章

如何用 python 读取硬件信息

如何在 Linux 上获取磁盘信息?

Inxi:获取Linux系统和硬件信息的神器

Inxi:获取Linux系统和硬件信息的神器

Inxi:获取Linux的系统和硬件信息

如何通过 .NETCore 获取 Linux,Mac 的硬件信息?