在哪里可以找到 HDD 的 SMART 阈值?
Where can I find the SMART Threshold values of a HDD?
我正在编写一个 SMART 监控工具,我设法使用 SMART_REA_DATA 命令获取 SMART 属性 [当前、最差、原始数据],但我也需要阈值,我搜索了 ATA documentation 但我还没有找到任何关于如何读取阈值的信息。有谁知道我可以从哪里获得这些值?
我找到了答案:)很简单。要获得阈值,您必须在功能寄存器 中使用 0xD1,并将其余部分配置为 0xD0 (SMART_READ_DATA) 命令。我没有找到它,因为 0xD1 它是一个过时的功能......但它似乎仍然在新硬盘中使用。
结果的结构可以是这样的:
SMART_ATTRIBUTE = packed record
ID: Byte;
case byte of
0: (Flags: Word;
CurrValue: Byte;
WorstValue: Byte;
RawData: array [0..5] of Byte;
Reserved0: Byte;);
1: (Threshold: Byte;
Reserved1: array [0..9] of Byte;);
end;
SMART_DATA = packed record
Version: Word;
Attribute: array [0..29] of SMART_ATTRIBUTE;
end;
以及用于检索属性和阈值的函数:
function GetSMARTData(Drive:Byte; Feature:Byte; var SMARTData:SMART_DATA):Boolean;
var hDrive: THandle;
atpexb: ATA_PASS_THROUGH_EX_WITH_BUFFERS;
bytesRet: DWord;
begin
//Result:=false;
hDrive:=CreateFile(PWideChar('\.\PhysicalDrive'+IntToStr(Drive)), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if hDrive = INVALID_HANDLE_VALUE then RaiseLastOSError;
try
bytesRet:=0;
FillChar(atpexb,SizeOf(atpexb),0);
atpexb.Length:=SizeOf(ATA_PASS_THROUGH_EX);
atpexb.AtaFlags:=ATA_FLAGS_DATA_IN;
atpexb.DataTransferLength:=512;
atpexb.TimeOutValue:=1;
atpexb.DataBufferOffset:=SizeOf(ATA_PASS_THROUGH_EX);
atpexb.CurrentTaskFile.Command:=WIN_SMART;
atpexb.CurrentTaskFile.Features:=Feature;
atpexb.CurrentTaskFile.LBA_Mid:=F;
atpexb.CurrentTaskFile.LBA_High:=$C2;
if not DeviceIoControl(hDrive, IOCTL_ATA_PASS_THROUGH, @atpexb, SizeOf(ATA_PASS_THROUGH_EX),
@atpexb, SizeOf(atpexb), bytesRet, nil) then RaiseLastOSError;
Result:=(atpexb.CurrentTaskFile.Command and 1)=0;
if Result then Move(atpexb.DataBuff, SMARTData, SizeOf(SMART_DATA));
finally
CloseHandle(hDrive);
end;
end;
我正在编写一个 SMART 监控工具,我设法使用 SMART_REA_DATA 命令获取 SMART 属性 [当前、最差、原始数据],但我也需要阈值,我搜索了 ATA documentation 但我还没有找到任何关于如何读取阈值的信息。有谁知道我可以从哪里获得这些值?
我找到了答案:)很简单。要获得阈值,您必须在功能寄存器 中使用 0xD1,并将其余部分配置为 0xD0 (SMART_READ_DATA) 命令。我没有找到它,因为 0xD1 它是一个过时的功能......但它似乎仍然在新硬盘中使用。
结果的结构可以是这样的:
SMART_ATTRIBUTE = packed record
ID: Byte;
case byte of
0: (Flags: Word;
CurrValue: Byte;
WorstValue: Byte;
RawData: array [0..5] of Byte;
Reserved0: Byte;);
1: (Threshold: Byte;
Reserved1: array [0..9] of Byte;);
end;
SMART_DATA = packed record
Version: Word;
Attribute: array [0..29] of SMART_ATTRIBUTE;
end;
以及用于检索属性和阈值的函数:
function GetSMARTData(Drive:Byte; Feature:Byte; var SMARTData:SMART_DATA):Boolean;
var hDrive: THandle;
atpexb: ATA_PASS_THROUGH_EX_WITH_BUFFERS;
bytesRet: DWord;
begin
//Result:=false;
hDrive:=CreateFile(PWideChar('\.\PhysicalDrive'+IntToStr(Drive)), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if hDrive = INVALID_HANDLE_VALUE then RaiseLastOSError;
try
bytesRet:=0;
FillChar(atpexb,SizeOf(atpexb),0);
atpexb.Length:=SizeOf(ATA_PASS_THROUGH_EX);
atpexb.AtaFlags:=ATA_FLAGS_DATA_IN;
atpexb.DataTransferLength:=512;
atpexb.TimeOutValue:=1;
atpexb.DataBufferOffset:=SizeOf(ATA_PASS_THROUGH_EX);
atpexb.CurrentTaskFile.Command:=WIN_SMART;
atpexb.CurrentTaskFile.Features:=Feature;
atpexb.CurrentTaskFile.LBA_Mid:=F;
atpexb.CurrentTaskFile.LBA_High:=$C2;
if not DeviceIoControl(hDrive, IOCTL_ATA_PASS_THROUGH, @atpexb, SizeOf(ATA_PASS_THROUGH_EX),
@atpexb, SizeOf(atpexb), bytesRet, nil) then RaiseLastOSError;
Result:=(atpexb.CurrentTaskFile.Command and 1)=0;
if Result then Move(atpexb.DataBuff, SMARTData, SizeOf(SMART_DATA));
finally
CloseHandle(hDrive);
end;
end;