如何读取硬盘的SMART信息

如何读取硬盘的SMART信息,第1张

前段时间买了 hp-dv1702 笔记本电脑, 酷睿单核 cpu, 5400 转硬盘, 看**挺不错的 酷睿 cpu支持 speedstep 技术, 不忙的时候总是工作在 800MHz 左右,发热量小,BIOS 设定风扇启动温度为 cpu 75度,平常工作中一天下来风扇也几乎不转,硬盘的温度比较高,从网上查到左手边热是这款本本的通病。

笔者的想法是让风扇在硬盘达到48、9度的时候让风扇转动起来,到设定的温度停下,并可以看到主板、cpu、硬盘的温度。在风扇控制完成以后,检测系统温度的问题就显出来了,一边用别人的软件看系统温度,一边手工来控制风扇的停和转动,累。

1、主板温度的检测

笔记本电脑的bios和台式机有一些区别,通常本本的bios ACPI 会有一个热度表述区(ThermalZone) 或其它acpi定义的温度检测区域,读出这个区域的数值,就得到当前主板上温度传感器的值,xp/2000 支持acpi,所以很方便读到。但台式机基本没有ThermalZone,要监测温度,需要扫描系统总线。

如何读取acpi这个区域的数值呢,windows driver 读取这些值用于管理,所以通过WMI 能读到。连接到 WMI 的名字空间,请参考 MSDN 'WMI C++ Application Examples'。这里不做叙述.

主板温度在wmi中有两个名字:1、ROOT\CIMV2\Win32_TemperatureProbe2、ROOT\WMI\MSAcpi_ThermalZoneTemperature 先检测 Win32_TemperatureProbe 是否有对象,如没有再检测 MSAcpi_ThermalZoneTemperature 然后读取成员 CurrentTemperature 为当前温度,CriticalTripPoint 为临界温度。此温度是以绝对 0 度开始并以 1/10 度增加,公式如下

当前摄氏度 = (CurrentTemperature - 2732) / 10

2、硬盘温度的监测

 检测硬盘温度的工具或软件,都是通过 SMART来读取,对硬盘直接 DeviceIoControl 或者 WMI 都可以得到SMART值.SMART 数据存储于 WMI 中 ROOT\WMI\MSStorageDriver_ATAPISmartData 命名空间中,其中属性 'VendorSpecific' 包含有硬盘温度的数据,这是ATA标准定义的。可能你读出这些数据来会有些困惑,其实这是一个结构,第一个和第二个字节代表 SMART 版本信息,从第三个字节起定义 SMART 的属性,每个属性为12字节长,每个属性的第一字节为当前属性定义,0x09 定义已经使用的小时数, 0xc2 为温度属性,第五字节表示当前温度。结构如下

struct SmartAttriubtes

{

char attrib;

char flags;

char worst;

char normal;

char current;

char current1;

char current2;

char current3;

char current4;

char current5;

char current6;

char current7;

}

struct VendorSpecific

{

unsigned short version;

SmartAttriubtes smartattrib [1];

}

如笔者硬盘读取如下数值,有些就省略了 {0xa, 0x00, 0x09, 0x32, 0, 0x63, 0x63, 0xc2, 0x03, 0, 0, 0, 0, 0, 0xc2, 0x22, 0, 0x2e, 0x3b, 0x2e, 0, 0, 0, 0x05, 0, 0, };

排列如下

{

0xa, 0x00 版本信息

0x09, 0x32, 0, 0x63, 0x63, 〔0xc2, 0x03〕, 0, 0, 0, 0, 0 硬盘使用小时数 这里是 0x3c2 = 962 小时

0xc2, 0x22, 0, 0x2e, 0x3b, 〔0x2e〕, 0, 0, 0, 0x05, 0, 0 这是当前温度 数值为 0x2e = 46 度

}

win2000 不支持此 WMI 属性,只能通过 DeviceIoControl 得到,如何实现请看考附录 SMART 的OpenSource 连接

3、CPU 的温度检测

新的酷瑞CPU和AMD的CPU 内部都集成有温度传感器DTS (Digital Thermal Sensor),每个核心有一个,以前的移动CPU好像也支持温度探测,但手头没有这样的CPU没法做测试.AMD 的温度值保存在 NB 寄存器中,酷瑞CPU 的 DTS 值保存在 MSR 0x19c 中,可以通过 rdmsr 来读取

这里只说酷睿CPU的读取过程

Intel 定义 eax=6 执行 cpuid, 然后测试 eax 第一位是否为1,如果为1表示CPU支持DTS ,当然之前应该以 eax=0 执行 cpuid 检测 eax 支持的最大命令数,如果小于6就肯定不支持DTS。

读取DTS:1 以 ecx=0xee 执行 rdmsr 指令, 测试 eax 的第30位是否为 1, 如果为 1 表示温度计算的初始值为 85 度否则表示从100度开始计算,这个值称为 Tjunction 然后以 ecx=0x19c 执行 rdmsr 指令, eax 的 16:23 位为表示当前DTS 值,这个值并不代表当前温度,而要以下面公式计算

当前cpu温度 = Tjunction - DTS

注意 signature 为 0x6f1, 0x6f0的 CPU DTS 值直接代表当前温度而不用Tjunction 相减 而 signature 小于等于 0x6f4 的 Tjunction 一直为100, 如果你是双核的cpu 可以使用 SetProcessAffinityMask API 来指定执行的CPU,以检测这个核心的温度。呵呵,我就不用啦,本本是单核的

另 rdmsr 指令需要运行在 0 级的代码才能执行所以写一个简单的驱动也是必须的

如果你想看看效果可以到我的共享资源中下载 FAN1702iirar 不 *** 作风扇他还是可以工作的

>

如何标识一台机器

在开发中,有时候我们需要获取唯一标识本机的序列号,你可能会想到如下几种

1) MAC地址

2) CPU ID

3) 硬盘ID

MAC地址

因为MAC地址可能会被修改,而且本机可能会有多张网卡,同时网卡的数量会随着网卡被启用或禁用而发生变化,所以暂时就不考虑使用MAC地址作为本机硬件标识了。

CPU ID

这个看起来不错,但是有个问题:CPU厂商有时候为了规避隐私问题,会对同一批次的CPU打上同一个ID,这样就不能通过CPU ID唯一的标识机器了。

硬盘ID

每一块硬盘在出厂的时候,厂商会烧录一个唯一的ID到硬盘中,这个标识通常可以获取到,并且可以作为机器ID,但是在比较老的硬盘上可能没有这个ID,另外在虚拟机中,也可能是获取不到硬盘ID的。哎,这种方法也是个问题。

综合以上的描述,我建议使用多种方法联合起来对机器进行标识,防止其中一个标识因无法获取而无法最终实现硬件唯一性标识。

下面我们通过WMI的方法来获取硬件序列号,这里以CPU ID为例。

WMI

WMI(Windows Management Instrumentation,Windows 管理规范)是一项核心的 Windows 管理技术;用户可以使用 WMI 管理本地和远程计算机。

WMI初始化

在使用WMI进行WQL语句查询之前,我们需要对WMI基础设施进行初始化。一般包含如下几个步骤:

1) COM库初始化(CoInitializeEx)

2) COM库安全机制初始化(CoInitializeSecurity)

3) 创建IWbemLocator接口实例(CoCreateInstance)

4) 连接至WMI服务(ConnectServer)

5) 设定请求代理的安全级别(CoSetProxyBlanket)

以下是具体代码片段

使用WQL进行查询

WMI支持WQL语句查询,这个WQL非常类似SQL,例如,查询CPU信息的语句如下:

SELECT FROM win32_Processor

读取CPU ID的步骤如下

1) 执行WQL查询语句(ExecQuery)

此调用会创建一个IEnumWbemClassObject接口的枚举器实例,后面会用到这个枚举器

2) 枚举CPU个数(Next),返回一个IWbemClassObject对象代表当前CPU

3) 调用IWbemClassObject对象的Get方法获取具体的属性,例如CPU ID。

4) 释放IWbemClassObject对象

5) 当枚举完毕,释放IEnumWbemClassObject对象

具体代码片段如下:

strResult += 磁盘类型: & SystemConvertToInt16(disk(DriveType)ToString())End IfMsgBox(strResult)NextEnd Sub总结:在VBNET中,用API函数可以获取硬盘信息。原来熟悉API函数VB6程序员,可以对API函数声明进行适当的更改后,进行调用。利用FSO(文件系统对象)的ScrrunDLL,也可以获得磁盘信息。在net Framwork中,利用WMI可以获取更多的关于机器硬件的详细信息(参考SystemManagement命名空间)。

有几种不同的方法可以获得单个用户的磁盘配额信息。具体选用何种方法取决于所安装的 Windows 版本。如果您运行的是 Windows XP 或 Windows 2003,那么可以通过 Win32_DiskQuota 类别获得某个用户的磁盘配额信息。例如,这里有一个脚本可以获得用户 kenmyer 的磁盘配额信息:strComputer = "" Set objWMIService = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") Set colQuotas = objWMIServiceExecQuery _ ("Select From Win32_DiskQuota Where " & _ "User=‘Win32_AccountDomain=""fabrikam"",Name=""kenmyer""‘") For Each objQuota in colQuotas WscriptEcho "Disk Space Used: " & objQuotaDiskSpaceUsed WscriptEcho "Limit: " & objQuotaLimit WscriptEcho "Quota Volume: " & objQuotaQuotaVolume intStatus = objQuotaStatus Select Case intStaus Case 0 strStatus = "OK" Case 1 strStatus = "Warning limit reached" Case 2 strStatus = "Quota exceeded" Case Else strStatus = "Unknown" End Select WscriptEcho "Status: " & strStatus WscriptEcho "Warning Limit: " & objQuotaWarningLimit Next 好的,WQL 查询看起来有点夸张(好多双引号!),但 Win32_DiskQuota 类别就是这么设计的:User 属性实际上是一个参考属性,是另一个对象和另一个类别(这里是 Win32_Account 类别)的指针。幸好,虽然不是非常好用,但也不难用。如果您想获得名为“carolphilips”的用户(其帐户在 contoso 域中)的配额信息,又该如何呢?很简单;只要将“kenmyer”替换为“carolphilips”,并将“fabrikam”替换为“contoso”就行了:Set colQuotas = objWMIServiceExecQuery _ ("Select From Win32_DiskQuota Where " & _ "User=‘Win32_AccountDomain=""contoso"",Name=""carolphilips""‘") 至少,脚本的其他部分非常简单;我们只回显各个属性的值。我们添加的唯一“有趣”的东西是一个 Select Case 语句,用于将 Status 属性返回的数值转化为可读的字符串。例如,如果返回的 Status 值为“2”,脚本就会把该值转化为字符串 Quota exceeded。此外,您可能只想让该脚本以 1024 来划分配额数。这将把这些值(以千字节为单位)转化为以兆字节为单位。顺便说一下,该脚本将返回用户 kenmyer 在计算机的所有驱动器上的磁盘配额信息。如果您只想获得单个驱动器的配额信息,又该怎么办呢?啊,真得问这个问题,不是吗?可以办到;只是由于 QuotaVolume 属性是另一个参考属性,WQL 查询看起来更加怪异:Set objQuota = objWMIServiceGet _ ("Win32_DiskQuotaQuotaVolume=‘Win32_LogicalDiskDeviceID=""C:""‘," & _ "User=‘Win32_AccountDomain=""tomservo"",Name=""Administrators""‘") 如果您需要其他驱动器的信息,只要复制上述查询并将“C:”替换为适当的驱动器号。当然,这个脚本在 Windows XP 和 Windows 2003 上非常好用,但是在 Windows 2000 上却行不通;这是因为 Windows 2000 不支持 Win32_DiskQuota 类别。(Windows NT 40 或 Windows 98 也不支持该类别,至少部分原因在于这些 Windows 版本不支持磁盘配额,就是这么回事。)那么如果您需要某台运行 Windows 2000 的计算机的磁盘配额信息,该怎么办呢?这时,您可以使用这个脚本,其利用 Shell 对象获得用户 kenmyer在本地计算机的驱动器 C: 上的磁盘配额信息:Set colDiskQuotas = CreateObject("MicrosoftDiskQuota1") colDiskQuotasInitialize "C:\", True Set objUser = colDiskQuotasFindUser("fabrikam\kenmyer") WscriptEcho "Logon name: " & objUserLogonName WscriptEcho "Quota limit: " & objUserQuotaLimit WscriptEcho "Quota threshold: " & objUserQuotaThreshold WscriptEcho "Quota used: " & objUserQuotaUsed 正如您所看到的,这个脚本真的是更简短更精炼,包含的双引号相对较少。我们为何不推荐您在 XP 或 Windows 2003 上使用该脚本呢?您可以随意使用。但是,使用 Shell 对象获取磁盘配额信息存在两个限制。其一,Shell 对象脚本只能在本地计算机上运行;不同于 WMI 脚本,您将无法连接到远程计算机并返回磁盘配额信息。其二,每次只能得到一个磁盘的配额信息。通过 WMI,可以返回包含计算机上所有驱动器的磁盘配额信息的集合。

以上就是关于如何读取硬盘的SMART信息全部的内容,包括:如何读取硬盘的SMART信息、求VBS获取电脑硬件信息,并保存、迈拓硬盘如何看序列号等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/10146495.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-05
下一篇2023-05-05

发表评论

登录后才能评论

评论列表(0条)

    保存