欢迎来到surface回收,surface维修服务网站!
打开客服菜单
微软surface服务首页 > 行业技术服务 > 硬盘内部温度 50°c是正常的嘛
硬盘内部温度 50°c是正常的嘛
编辑 : 微软surface回收 时间 : 2017-09-08 17:58 浏览量 : 88

  最近在研究硬盘温度的获取。看来ata spec,疯狂的在网上查找资料,还有就是分析hwmonitor.exe(这个帮助最大)。刚开始的时候什么都不会,到什么地方获取数据呢。在之前获取dmi中,有在spec中看到有温度。但是这个一般的主板商是不会写温度数据到里面的。而wmi很多就是读取dmi数据的。所以在获取cpu温度等上面,都是读不出数据的。因此,首先打消这个念头。

    在疯狂的在网上搜寻资料之后,得到了一些有用的东西,那就是温度是在硬盘的SMART属性中有保存的。到这里我们知道了,硬盘温度保存的地方。如何获取到这部分数据呢。是怎样的一个数据结构呢?真正的问题来了。用smart获取硬盘温度,你可以再codeproject中会找一个工程。实例就是如何获取smart信息。很详细。建议看看这部分代码。他是通过读取//./PhysicalDrive0(第一块硬盘,之后一次类推)。但是有时候根本获取不到详细的属性信息。特别是在多硬盘的机器上,很可能会出现获取数据不正确的问题,主要的原因就是sata硬盘的问题。在使用codeproject中的样例就获取不到了,到这里这能另寻它路了。没有别的办法只有看spec了。看这书,我是有点看晕了。只能求救于网络了。很幸运,找到新大陆了,可以通过wmi方式得到属性值。既然这样那就用wmitools看看吧。下面把网上找到的内容粘上给大家参考一下:

   检测硬盘温度的工具或软件,都是通过 S.M.A.R.T来读取,对硬盘直接 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 连接


    


     确实如上面说的,2000下面没有这个东西。但是用wmi方式同样和用codeproject中的样例一样会有相同的问题。这下真的让人很郁闷。


    只有最后一招了,调试分析hwmonitor了(逆向,还好一点点还是会的)。下面是主要分析:


//获取当前系统上的存储设备信息

InBuffer:

0012EDC4  00 00 00 00 00 00 00 00 E0 ED 12 00              ....?



00414272  |> /57            push    edi                              ; /pOverlapped

00414273  |. |8D5424 38     lea     edx, dword ptr [esp+38]          ; |

00414277  |. |52            push    edx                              ; |pBytesReturned

00414278  |. |8B5424 1C     mov     edx, dword ptr [esp+1C]          ; |

0041427C  |. |68 00020000   push    200                              ; |OutBufferSize = 200 (512.)

00414281  |. |8D4424 50     lea     eax, dword ptr [esp+50]          ; |

00414285  |. |50            push    eax                              ; |OutBuffer

00414286  |. |6A 0C         push    0C                               ; |InBufferSize = C (12.)

00414288  |. |8D4C24 4C     lea     ecx, dword ptr [esp+4C]          ; |

0041428C  |. |51            push    ecx                              ; |InBuffer

0041428D  |. |68 00142D00   push    2D1400                           ; |IoControlCode = 2D1400(IOCTL_STORAGE_QUERY_PROPERTY)

00414292  |. |52            push    edx                              ; |hDevice

00414293  |. |897C24 58     mov     dword ptr [esp+58], edi          ; |

00414297  |. |897C24 5C     mov     dword ptr [esp+5C], edi          ; |

0041429B  |. |FF15 BC034A00 call    dword ptr [<&KERNEL32.DeviceIoCo>; /DeviceIoControl


//获取smart版本



00414365  |> /57            push    edi                              ; /pOverlapped

00414366  |.  8D4C24 34     lea     ecx, dword ptr [esp+34]          ; |

0041436A  |.  51            push    ecx                              ; |pBytesReturned

0041436B  |.  6A 18         push    18                               ; |OutBufferSize = 18 (24.)

0041436D  |.  33C0          xor     eax, eax                         ; |

0041436F  |.  8D5424 24     lea     edx, dword ptr [esp+24]          ; |

00414373  |.  52            push    edx                              ; |OutBuffer

00414374  |.  57            push    edi                              ; |InBufferSize

00414375  |.  57            push    edi                              ; |InBuffer

00414376  |.  894424 30     mov     dword ptr [esp+30], eax          ; |

0041437A  |.  894424 34     mov     dword ptr [esp+34], eax          ; |

0041437E  |.  894424 38     mov     dword ptr [esp+38], eax          ; |

00414382  |.  894424 3C     mov     dword ptr [esp+3C], eax          ; |

00414386  |.  894424 40     mov     dword ptr [esp+40], eax          ; |

0041438A  |.  894424 44     mov     dword ptr [esp+44], eax          ; |

0041438E  |.  8B4424 2C     mov     eax, dword ptr [esp+2C]          ; |

00414392  |.  68 80400700   push    74080                            ; |IoControlCode = SMART_GET_VERSION

00414397  |.  50            push    eax                              ; |hDevice

00414398  |.  897C24 50     mov     dword ptr [esp+50], edi          ; |

0041439C  |.  FF15 BC034A00 call    dword ptr [<&KERNEL32.DeviceIoCo>; /DeviceIoControl


0012ED6C   00000148  |hDevice = 00000148

0012ED70   00074080  |IoControlCode = SMART_GET_VERSION

0012ED74   00000000  |InBuffer = NULL

0012ED78   00000000  |InBufferSize = 0

0012ED7C   0012EDA4  |OutBuffer = 0012EDA4

0012ED80   00000018  |OutBufferSize = 18 (24.)

0012ED84   0012EDBC  |pBytesReturned = 0012EDBC

0012ED88   00000000  /pOverlapped = NULL


.text:004143AC                 mov     ecx, [esp+254h+var_238] ; GETVERSIONINPARAMS.fCapabilities

.text:004143B0                 shr     ecx, 2   

.text:004143B3                 and     ecx, 1

.text:004143B6                 mov     [ebx+718h], ecx

.text:004143BC                 jmp     short loc_4143C0


if(GETVERSIONINPARAMS.fCapabilities & CAP_SMART_CMD ) == CAP_SMART_CMD)

{


}


 


 


//发送smart命令


0012EDF0  00 00 00 00 D8 01 01 4F C2 A0 B0 00 00 00 00 00  ..ǘ企?°..

0012EE00  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........


 



.text:00414195                 mov     [eax+6], dl

.text:00414198                 mov     edx, [esp+1Ch+lpOutBuffer]

.text:0041419C                 push    edx             ; lpOutBuffer

.text:0041419D                 push    20h             ; nInBufferSize

.text:0041419F                 push    eax             ; lpInBuffer

.text:004141A0                 mov     [eax], esi

.text:004141A2                 mov     esi, [esp+28h+hObject]

.text:004141A6                 or      bl, 0FAh

.text:004141A9                 push    7C084h          ; dwIoControlCode  SMART_SEND_DRIVE_COMMAND

.text:004141AE                 shl     bl, 4

.text:004141B1                 push    esi             ; hDevice

.text:004141B2                 mov     byte ptr [eax+4], 0D8h

.text:004141B6                 mov     byte ptr [eax+7], 4Fh

.text:004141BA                 mov     byte ptr [eax+8], 0C2h

.text:004141BE                 mov     [eax+9], bl

.text:004141C1                 mov     byte ptr [eax+0Ah], 0B0h

.text:004141C5                 call    ds:DeviceIoControl ; Sends a control code directly to a specified device driver,

.text:004141C5                                         ; causing the corre



//接受smart数据


0012EDF0  00 02 00 00 D0 01 01 4F C2 A0 B0 00 00 00 00 00  ?.ǐ企?°..

0012EE00  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........


.text:004145B5                 call    _memset

.text:004145BA                 add     esp, 0Ch

.text:004145BD                 push    0               ; lpOverlapped

.text:004145BF                 lea     edx, [esp+288h+BytesReturned]

.text:004145C3                 push    edx             ; lpBytesReturned

.text:004145C4                 push    210h            ; nOutBufferSize

.text:004145C9                 lea     eax, [esp+290h+Dst]

.text:004145CD                 push    eax             ; lpOutBuffer

.text:004145CE                 push    20h             ; nInBufferSize

.text:004145D0                 lea     ecx, [esp+298h+InBuffer]

.text:004145D4                 push    ecx             ; lpInBuffer

.text:004145D5                 push    7C088h          ; dwIoControlCode  SMART_REV_DRIVE_DATA

.text:004145DA                 push    ebp             ; hDevice

.text:004145DB                 call    ds:DeviceIoControl ; Sends a control code directly to a specified device driver,

.text:004145DB                                         ; causing the corresponding dev


 



while(SetupDiEnumDeviceInterfaces())

{

 //获取所需的缓存大小

 if(SetupDiGetDeviceInterfaceDetail())

 {

  //获取所需的数据

  if(SetupDiGetDeviceInterfaceDetail())

  {

   //打开设备,设备名为获取buffer+4

    hFile = CreateFile();

    if(hFile != INVAILD_VALUE_HANDLE)

    {

     CloseHanle(hFile);

    } 

   

  }

 }

}


上面的inbuffer内容,具体的要看ata spec了。


可以尝试的调试分析一下,你会知道,在获取smart之前是打开设备。分析中你会知道它不是打开//./PhysicalDrive0之类的设备,而是首先通过存储设备类,知道有哪些可用的存储设备,使用SetDixxxxxxx函数可以得到具体设备名。然后GetPowerState得到设备是否正在运行,以及通过smart版本是否支持smart命令。如果这些都成立的话,那么就可以通过send smart命令进行下面的操作了。这个存储设备类的guid是{0x53f56307,0xb6bf,0x11do,0x94,0xf2,0x00,0xa0,0xc9,0x1e,0xfb,0x8b}.成都硬盘维修服务中心


    在得到了smart属性之后就是解析的问题的。每个smart属性都是0xc字节大小,这个上面有说的。属性type为0xC2就是温度属性了。在偏移为5的地方就是当前温度值。在到每个属性之前有0x12字节的数据(这个是什么我就不管了)。上面还有一点没有说到的就是设备属性的获取。可以得到vendorid,和products,这个我是用来表示硬盘名称的。

  硬盘(港台称之为硬碟,英文名:Hard Disk Drive 简称HDD 全名 温彻斯特式硬盘)是电脑主要的存储媒介之一,由一个或者多个铝制或者玻璃制的碟片组成。碟片外覆盖有铁磁性材料。

  硬盘有固态硬盘(SSD 盘,新式硬盘)、机械硬盘(HDD 传统硬盘)、混合硬盘(HHD 一块基于传统机械硬盘诞生出来的新硬盘)。SSD采用闪存颗粒来存储,HDD采用磁性碟片来存储,混合硬盘(HHD: Hybrid Hard Disk)是把磁性硬盘和闪存集成到一起的一种硬盘。绝大多数硬盘都是固定硬盘,被永久性地密封固定在硬盘驱动器中。

  磁头复位节能技术:通过在闲时对磁头的复位来节能。

  多磁头技术:通过在同一碟片上增加多个磁头同时的读或写来为硬盘提速,或同时在多碟片同时利用磁头来读或写来为磁盘提速,多用于服务器和数据库中心。

cache
Processed in 0.009499 Second.