(四)LibreHardwareMonitor 扩展硬件支持

部署运行你感兴趣的模型镜像

系列文章目录

【开源项目分享】可监控电脑CPU、显卡、内存等硬件的温度、功率和使用情况
(一)开源的硬件监控工具 LibreHardwareMonitor
(二)LibreHardwareMonitor 分层架构设计
(三)LibreHardwareMonitor 硬件检测机制
(四)LibreHardwareMonitor 扩展硬件支持



前言

本文档详细说明了如何为 LibreHardwareMonitor 项目添加对新硬件设备的支持,包括 CPU、GPU、主板芯片组和存储设备。

其项目结构清晰,按硬件类型和功能进行模块化组织。核心硬件支持位于 LibreHardwareMonitorLib 目录下,其中 Hardware 子目录包含了 CPU、GPU、主板、内存、网络和存储等主要硬件组件的实现。

每个硬件类别都有其专用的文件夹,如 Cpu、Gpu、Motherboard 和 Storage,这些文件夹内包含了针对特定品牌或型号的驱动程序和通用基类。

在这里插入图片描述


一、CPU硬件支持扩展

目录结构

项目结构清晰地组织了CPU监控相关的所有实现文件,主要位于LibreHardwareMonitorLib/Hardware/Cpu目录下。

在这里插入图片描述

核心组件

CPU监控系统的核心组件包括CpuGroup、GenericCpu、CpuId和CpuLoad。

  • CpuGroup负责CPU的发现和硬件组的创建;
  • GenericCpu作为所有CPU实现的基类,提供了通用的传感器初始化和更新逻辑;
  • CpuId封装了CPUID指令的调用,用于获取CPU的详细信息;
  • CpuLoad则负责计算CPU的负载。

CPU识别与硬件组注册

CPU的识别和硬件组注册由CpuGroup类完成。该类在构造函数中通过GetProcessorThreads方法枚举系统中的所有CPU线程,并根据CPUID信息将线程分组到不同的处理器和核心中。

在这里插入图片描述

CpuGroup根据CpuId获取的Vendor和Family信息,决定实例化哪个具体的CPU类。例如:

  • 对于AMD处理器,会根据Family的值选择Amd0FCpu、Amd10Cpu或Amd17Cpu。
  • 对于Intel处理器,则实例化IntelCpu。

这个过程在CpuGroup的构造函数中通过一系列switch语句实现,确保了新CPU型号可以通过添加新的case分支来支持。

基类与传感器初始化

GenericCpu类作为所有CPU实现的基类,定义了传感器初始化和更新的通用逻辑。它继承自Hardware类,并在构造函数中完成了大部分初始化工作。

在这里插入图片描述

GenericCpu的构造函数首先从CpuId信息中提取CPU的基本属性,如核心数、线程数等。
然后,它检查CPU是否支持模型特定寄存器(MSR)和时间戳计数器(TSC)。
接着,它创建了用于监控CPU负载的传感器,包括每个线程的负载、总负载和最大核心负载。CpuLoad类被用来计算这些负载值。
最后,它通过EstimateTimeStampCounterFrequency方法估算TSC的频率,为后续的时钟频率计算提供基础。

AMD与Intel处理器实现差异

AMD和Intel处理器在温度、电压和频率的监控实现上存在显著差异,这主要体现在它们使用的底层硬件接口和寄存器上。

Intel处理器实现

IntelCpu类继承自GenericCpu,并重写了GetMsrs和Update方法。它通过读取MSR寄存器来获取温度、电压和频率信息。

在这里插入图片描述

IntelCpu使用IA32_THERM_STATUS_MSR寄存器来获取每个核心的温度,通过IA32_PERF_STATUS寄存器来获取核心电压和时钟频率。它还支持通过RAPL(Running Average Power Limit)接口读取CPU的功耗信息。

AMD处理器实现

AmdCpu是一个抽象基类,而Amd17Cpu是针对AMD Zen架构的具体实现。Amd17Cpu使用了PCI配置空间和SMU(System Management Unit)来获取监控数据。

在这里插入图片描述

Amd17Cpu通过读取PCI配置空间中的特定寄存器来获取核心和SoC的电压,通过MSR寄存器来获取功耗和时钟频率。它还利用SMU来获取更详细的传感器数据。与Intel不同,AMD的实现需要处理NUMA节点和CCD(Core Complex Die)的复杂拓扑结构。

多核心负载计算

多核心负载的计算由CpuLoad类负责。该类通过查询操作系统提供的性能信息来计算每个线程和整个CPU的负载。

在这里插入图片描述

CpuLoad的Update方法首先获取当前的空闲时间和总时间,然后与上一次的值进行比较,计算出时间间隔内的负载。

  • 对于Windows系统,它使用NtQuerySystemInformation API来获取SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION。
  • 对于Unix系统,它读取/proc/stat文件。计算出的负载值会被GenericCpu类用来更新相应的传感器。

二、GPU硬件支持扩展

下面将讲解如何为NVIDIA、AMD和Intel集成显卡添加GPU监控支持。

  • 基于GenericGpu基类,描述如何实现特定厂商的传感器读取逻辑,如NvidiaGpu.cs中通过NVAPI接口获取核心温度、风扇转速和功耗数据。
  • 分析AmdGpu.cs中对ADL(AMD Display
    Library)的调用机制,以及IntelIntegratedGpu.cs中对Intel GPU寄存器的访问方式。
  • 说明GpuGroup的设备枚举流程和驱动版本兼容性处理策略。

组织结构

主要相关目录和文件包括LibreHardwareMonitorLib/Hardware/Gpu,其中包含了所有GPU相关的实现。

在这里插入图片描述

核心组件

GPU监控的核心组件围绕GenericGpu抽象基类构建,该基类继承自Hardware,为所有GPU实现提供了统一的接口。

GenericGpu定义了DeviceId属性,该属性必须由所有派生类实现,用于获取设备的唯一标识符。

具体的GPU监控功能由NvidiaGpu、AmdGpu和IntelIntegratedGpu三个类分别实现,它们各自通过不同的底层API与硬件交互。

GPU 架构概述

整个GPU监控系统的架构遵循了分层和抽象的设计原则。顶层是IGroup接口,由NvidiaGroup、AmdGpuGroup和IntelGpuGroup实现,负责设备的枚举和初始化。

这些Group类在初始化时会调用相应的底层API(如NVAPI、ADL)来发现系统中的GPU设备。一旦设备被发现,Group类就会创建对应的GenericGpu派生类实例(如NvidiaGpu)。这些具体的GPU类负责通过厂商特定的API读取传感器数据,并在Update方法中更新其内部的传感器值。

在这里插入图片描述

详细组件分析

NVIDIA GPU监控实现

NvidiaGpu类通过NVIDIA的NVAPI和NVML库来获取详细的硬件信息。在构造函数中,它首先通过NvAPI_GPU_GetThermalSettings获取温度传感器信息,并为每个传感器创建Sensor对象。

然后,它尝试通过NvAPI_GPU_GetPCIIdentifiers获取PCI设备ID,并通过NvAPI_GPU_GetDynamicPstatesInfoEx或NvAPI_GPU_GetUsages获取GPU负载。

对于功耗和PCIe吞吐量等高级信息,它会尝试初始化NVML库,并通过NvmlDeviceGetHandleByPciBusId获取设备句柄。Update方法是核心,它周期性地调用这些API来刷新所有传感器的值。

** NVIDIA GPU类图 **
在这里插入图片描述

AMD GPU监控实现

AmdGpu类依赖于AMD Display Library (ADL) 来与GPU通信。它的构造函数首先初始化ADL上下文,然后通过ADL2_Adapter_MemoryInfoX4_Get获取显存总量。它通过ADL2_Adapter_PMLog_Support_Get检查PM Log(Power Monitoring Log)是否受支持,这是获取现代AMD GPU传感器数据的主要方式。

同时,它也支持较旧的Overdrive 5/6 API作为后备方案。Update方法会根据可用的API优先级来读取数据:优先使用PM Log,其次是Overdrive N(OD8),最后是Overdrive 5。

AMD GPU类图

在这里插入图片描述

Intel集成GPU监控实现

IntelIntegratedGpu类的实现相对简单,主要依赖于D3D API和MSR(Model Specific Register)寄存器。它通过D3DDisplayDevice.GetDeviceInfoByIdentifier获取显存使用情况。

对于功耗监控,它直接读取Intel CPU的MSR寄存器MSR_PP1_ENERGY_STATUS(0x641),该寄存器记录了GPU的能耗。通过计算连续两次读取之间的能耗差值除以时间间隔,即可得到实时功耗。这种方法巧妙地利用了Intel CPU和集成GPU共享功耗监控机制的特点。

Intel集成GPU类图

在这里插入图片描述

依赖关系

GPU监控模块的依赖关系清晰。GenericGpu是所有具体GPU实现的基类,定义了公共接口。NvidiaGpu、AmdGpu和IntelIntegratedGpu都直接依赖于GenericGpu。

设备枚举类(NvidiaGroup、AmdGpuGroup、IntelGpuGroup)则依赖于具体的GPU实现类来创建实例。此外,这些类还依赖于Interop命名空间中的外部API声明,以及D3DDisplayDevice等工具类来获取通用的硬件信息。

在这里插入图片描述

小结

LibreHardwareMonitor通过精心设计的GenericGpu基类和厂商特定的派生类,成功实现了对NVIDIA、AMD和Intel GPU的全面监控。它利用NVAPI、ADL和MSR等底层技术,能够准确地读取核心温度、风扇转速、功耗、时钟频率和显存使用情况等关键指标。GpuGroup类负责设备的发现和初始化,确保了系统的可扩展性和健壮性。这种模块化的设计使得添加对新GPU厂商或新传感器类型的支持变得相对简单。

三、主板硬件支持扩展

下面将以Nct677X.cs和IT87XX.cs为例,说明了如何通过LPC总线读取硬件监控芯片寄存器,并将原始数据解析为可用的传感器值。接着介绍SuperIOHardware抽象层的作用及MotherboardGroup的自动识别机制。

目录结构

核心硬件监控功能位于LibreHardwareMonitorLib目录下,其中Hardware子目录包含了所有硬件组件的实现。主板相关的监控功能集中在Motherboard文件夹中,特别是Lpc子目录,它包含了对Super I/O芯片(如NCT677X和IT87XX)的具体支持。

核心组件

本项目的核心是能够通过LPC总线与主板上的Super I/O芯片通信,读取其寄存器中的电压、温度和风扇转速等原始数据,并将其转换为用户可读的传感器值。这一过程涉及多个关键组件:

  • ISuperIO接口定义了所有Super I/O芯片的通用契约;
  • Nct677X和IT87XX类是具体芯片的实现;
  • LpcIO类负责在系统启动时检测和初始化这些芯片;
  • SuperIOHardware类则作为抽象层,将底层芯片数据暴露给上层应用。

架构概述

同样是遵循分层设计原则,最底层是直接与硬件交互的LpcIO类,它利用Ring0库提供的底层I/O端口读写能力。

中间层是实现了ISuperIO接口的具体芯片类,如Nct677X和IT87XX,它们封装了特定芯片的寄存器布局和通信协议。

最上层是SuperIOHardware类,它作为硬件抽象层,将来自不同芯片的异构数据统一为标准的传感器模型,供UI或其他模块使用。

Motherboard类作为容器,管理着一个或多个SuperIOHardware实例。

在这里插入图片描述

详细组件分析

Nct677X芯片实现分析

Nct677X类是Nuvoton(新唐科技)NCT677X系列Super I/O芯片的具体实现。它通过LpcPort对象与LPC总线通信。

在构造函数中,根据不同的芯片型号(如Chip.NCT6771F, Chip.NCT6796D等)初始化其内部数组,如:

  • _voltageRegisters(电压寄存器地址)
  • _fanRpmRegister(风扇转速寄存器地址)
  • _temperaturesSource(温度源数据结构)

_temperaturesSource是一个关键结构,它不仅包含温度读数的寄存器地址,还可能包含半位(half-bit)和源寄存器(source register),用于处理更复杂的温度传感器。

Nct677X数据更新流程

Update()方法是数据采集的核心。它首先检查芯片厂商ID以确保通信正常。然后,它通过Mutexes.WaitIsaBus()获取对ISA总线的独占访问权,防止与其他程序冲突。

电压读取通过读取_voltageRegisters数组中的地址实现,对于NCT668x系列芯片,电压值由两个字节组成,需要进行12位精度的计算。

温度读取逻辑复杂,它使用一个temperatureSourceMask位掩码来防止重复读取同一温度源。它会读取主寄存器和半位寄存器,将结果左移一位后与半位进行或运算,得到一个16位的值,然后乘以0.5得到最终的摄氏度温度。

风扇转速读取根据芯片型号使用16位计数器或传统的8位计数器。最后,SetControl()方法允许软件控制风扇转速,它会先保存当前的控制模式,然后写入新的PWM值。

在这里插入图片描述

IT87XX芯片实现分析

IT87XX类是ITE(联阳)IT87XX系列Super I/O芯片的实现。与Nct677X类似,它在构造函数中根据Chip枚举的值来初始化其传感器数组(Voltages, Temperatures, Fans, Controls)和特定的芯片属性,如:

  • _voltageGain(电压增益系数)
  • _has16BitFanCounter(是否支持16位风扇计数器)

_voltageGain的值因芯片型号而异,例如IT8625E使用0.011,而IT8655E使用0.0109,这反映了不同芯片内部ADC的参考电压差异。

IT87XX数据更新流程

Update()方法同样需要获取ISA总线锁。电压读取非常直接:读取IT87_REG_VIN[i]寄存器的值,然后乘以_voltageGain。

温度读取则读取TEMPERATURE_BASE_REG + i地址的有符号字节值。

风扇转速读取逻辑根据_has16BitFanCounter标志分为两种情况:

  • 如果支持16位计数器,则读取两个寄存器并组合成一个16位值;
  • 否则,使用8位计数器,并根据FAN_TACHOMETER_DIVISOR_REGISTER中的分频器值来计算实际转速。

风扇控制读取(Controls)也分为两种模式:

  • 如果_hasExtReg为真,则PWM值分布在两个寄存器中,需要读取扩展寄存器才能获得完整的8位值;
  • 否则,只使用7位精度。

在这里插入图片描述

SuperIOHardware抽象层分析

SuperIOHardware类是连接底层芯片实现和上层应用的关键抽象层。它在构造函数中接收一个ISuperIO实例,并根据主板型号和制造商调用GetBoardSpecificConfiguration方法来获取该主板上Super I/O芯片的特定配置,如哪些电压、温度、风扇和控制通道是可用的。

然后,它为每个可用的传感器创建一个Sensor对象,并将这些对象分别添加到_voltages、_temperatures、_fans和_controls列表中。当上层应用调用Update()方法时,SuperIOHardware会调用其内部_superIO.Update()方法来刷新原始数据,然后这些数据就可以通过Sensors属性被访问。

MotherboardGroup自动识别机制分析

MotherboardGroup类的实现非常简洁,它只包含一个Motherboard实例的数组。其自动识别机制的核心在于Motherboard类的构造函数。

当Motherboard被创建时,它会首先通过SMBios获取主板的制造商和型号信息。然后,根据操作系统,它会创建LpcIO(Windows)或LMSensors(Unix)实例。LpcIO的构造函数会立即执行Detect()方法,该方法会遍历预定义的LPC端口(如0x2E, 0x4E),尝试进入Winbond/Fintek和ITE芯片的配置模式,并读取芯片ID。根据读取到的ID,LpcIO会创建相应的Nct677X或IT87XX实例,并将其添加到_superIOs列表中。

最后,Motherboard会为_superIOs中的每个芯片创建一个SuperIOHardware实例,并将其作为子硬件(SubHardware)。

依赖分析

Motherboard依赖于LpcIO和SuperIOHardware。LpcIO是检测逻辑的核心,它依赖于ISuperIO接口和具体的芯片实现类(Nct677X, IT87XX)。

SuperIOHardware依赖于ISuperIO来获取数据。所有与硬件的直接交互都通过Ring0库完成,它提供了ReadIoPort和WriteIoPort等底层函数。Mutexes类用于确保对ISA总线的独占访问,防止数据竞争。

在这里插入图片描述

扩展建议

为新型号主板的Super I/O芯片添加支持,需要深入理解LPC总线通信协议和特定芯片的寄存器手册。通过遵循ISuperIO接口,可以将新芯片的实现无缝集成到现有的SuperIOHardware抽象层中。LpcIO类的自动检测机制通过枚举端口和读取芯片ID来发现硬件,而Motherboard类则负责将这些发现的硬件组织成一个完整的监控树。成功实现的关键在于精确的寄存器映射、正确的数据解析算法以及对硬件访问权限和稳定性的谨慎处理。

四、存储设备支持扩展

系统基于INVMeDrive接口,实现了对不同厂商NVMe命令集的解析,包括Intel RST驱动下的健康信息读取和三星专有SMART属性的处理。通过WindowsStorage类与磁盘驱动通信,提取温度、磨损指数和坏块计数等关键指标。

组织结构

核心功能位于LibreHardwareMonitorLib目录下,其中Hardware\Storage子目录包含了所有与存储设备相关的实现。

在这里插入图片描述

核心组件

核心组件包括INVMeDrive接口、厂商特定的NVMe驱动实现(如NVMeIntel、NVMeSamsung)以及WindowsStorage类。这些组件共同协作,通过IOCTL请求与底层驱动通信,获取NVMe和SATA设备的健康状态和性能指标。

详细组件分析

NVMe驱动接口分析

INVMeDrive接口是所有NVMe驱动实现的基础,定义了三个核心方法:Identify用于获取设备句柄,IdentifyController用于获取控制器信息,HealthInfoLog用于读取健康信息日志。

在这里插入图片描述

Intel NVMe驱动实现分析

NVMeIntel类实现了Intel NVMe设备的专有通信协议。它使用IOCTL_SCSI_MINIPORT控制码和特定的签名(IntelNVMeMiniPortSignature1)来与Intel驱动通信。

Intel RST驱动实现分析

NVMeIntelRst类专门处理在Intel RST(快速存储技术)RAID模式下的NVMe设备。与NVMeIntel的主要区别在于使用的签名不同(IntelNVMeMiniPortSignature2),以适应RAID控制器的通信协议。

在这里插入图片描述

三星NVMe驱动实现分析

NVMeSamsung类通过SCSI安全协议命令(SECURITY PROTOCOL IN)与三星NVMe设备通信。它使用特定的CDB(命令描述块)序列来读取识别信息和健康日志。

Windows存储通信机制分析

WindowsStorage类通过IOCTL_STORAGE_QUERY_PROPERTY控制码与Windows存储子系统通信,获取设备的基本信息。

在这里插入图片描述

依赖分析

系统依赖于Windows API进行底层设备访问,主要通过Kernel32命名空间中的P/Invoke调用。DeviceIoControl函数是核心,用于发送各种IOCTL请求。INVMeDrive接口的实现依赖于具体的厂商协议,而NVMeSmart类则负责根据设备型号选择正确的驱动实现。

在这里插入图片描述

总结

为 LibreHardwareMonitor 添加新硬件支持是一个结构化的过程。对于 CPU,关键是继承 GenericCpu 并在 CpuGroup 中根据 CPUID 进行注册。对于 Super I/O 芯片,需要实现 ISuperIO 接口,并利用 LpcPort 安全地读写寄存器。对于 NVMe 存储设备,需要实现 INVMeDrive 接口,并通过 WindowsStorage 类集成到设备发现流程中。在整个过程中,必须严格处理硬件 ID 识别、驱动兼容性以及异常和资源管理,以确保软件的稳定性和可靠性。

项目地址

项目地址:https://github.com/LibreHardwareMonitor/LibreHardwareMonitor

如果访问不了GitHub,可下载我整理的压缩包,里面包含如下内容:
1、LibreHardwareMonitor-master.zip(GitHub下载的源码)
2、net472.zip(本地编译后的exe文件,实测可在Windows11正常运行使用)
3、README.zh-CN.md(项目描述文件)
4、目录文件说明.md(源码目录说明)
【点击下载(需要5积分)】

您可能感兴趣的与本文相关的镜像

Wan2.2-I2V-A14B

Wan2.2-I2V-A14B

图生视频
Wan2.2

Wan2.2是由通义万相开源高效文本到视频生成模型,是有​50亿参数的轻量级视频生成模型,专为快速内容创作优化。支持480P视频生成,具备优秀的时序连贯性和运动推理能力

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值