
各属性には、識別子、タイプ(クリティカル、パフォーマンスインジケーター、エラーカウンター、イベントカウンター)、現在の値、しきい値(現在のしきい値がしきい値よりも小さい場合-新しいディスクの検索を開始する)、最低、固定の属性値があります。 ここで各属性の説明を見つけることができます 。
これで理論的な部分は終わりましたので、実践に移りましょう。 SMART属性を読み取って表示するプログラムを作成します。完成したプログラムは、ソースと共にこちらからダウンロードできます。

まず、興味のある情報を受け取る構造を決定します。
//
typedef struct _DRIVEATTRIBUTEHDR
{
//
WORD wRevision;
//
BYTE bData[1];
}
DRIVEATTRIBUTEHDR, *PDRIVEATTRIBUTEHDR, *LPDRIVEATTRIBUTEHDR;
// SMART
typedef struct _DRIVEATTRIBUTE
{
//
BYTE bAttrID;
// (, ..)
WORD wStatusFlags;
//
BYTE bAttrValue;
// , ,
BYTE bWorstValue;
// ,
BYTE bRawValue[6];
BYTE bReserved;
}
DRIVEATTRIBUTE, *PDRIVEATTRIBUTE, *LPDRIVEATTRIBUTE;
// Threshold ( ) SMART
typedef struct _ATTRTHRESHOLD
{
//
BYTE bAttrID;
//
BYTE bWarrantyThreshold;
BYTE bReserved[10];
}
ATTRTHRESHOLD, *PATTRTHRESHOLD, *LPATTRTHRESHOLD;
* This source code was highlighted with Source Code Highlighter .
すべてはディスク記述子の取得から始まります。
HANDLE hDrive = CreateFile( "\\\\.\\PHYSICALDRIVE0" , GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
* This source code was highlighted with Source Code Highlighter .
ここで、 「\\\\。\\ PHYSICALDRIVE0」の 0は、システム内の物理ディスクの番号を意味します。
記述子を受け取った後、 SENDCMDINPARAMS構造に記入する必要があります
SENDCMDINPARAMS cmdIn = {0};
//
cmdIn.cBufferSize = READ_ATTRIBUTE_BUFFER_SIZE;
// IDE
cmdIn.irDriveRegs.bCommandReg = SMART_CMD;
//
cmdIn.irDriveRegs.bFeaturesReg = READ_ATTRIBUTES;
// ,
cmdIn.irDriveRegs.bCylLowReg = SMART_CYL_LOW;
// ,
cmdIn.irDriveRegs.bCylHighReg = SMART_CYL_HI;
//
cmdIn.irDriveRegs.bSectorCountReg = 1;
//
cmdIn.irDriveRegs.bSectorNumberReg = 1;
// \ IDE
cmdIn.irDriveRegs.bDriveHeadReg = 0xA0 | (((BYTE)nDrive & 1) << 4);
* This source code was highlighted with Source Code Highlighter .
リクエスト属性:
BYTE bOutAttributes[ sizeof (SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1] = {0};
DeviceIoControl(hDrive, SMART_RCV_DRIVE_DATA, &cmdIn, sizeof (cmdIn), bOutAttributes, sizeof (bOutAttributes), &dwReturn, NULL);
* This source code was highlighted with Source Code Highlighter .
成功した場合、属性はbOutAttributes バッファーに書き込まれます。 ポインターを変換して、構造体の配列のように操作できるようにします
//
LPDRIVEATTRIBUTEHDR lpAttrHdr = (LPDRIVEATTRIBUTEHDR)(((LPSENDCMDOUTPARAMS)bOutAttributes)->bBuffer);
//
LPDRIVEATTRIBUTE lpAttr = (LPDRIVEATTRIBUTE)(lpAttrHdr->bData);
// -
// NUM_ATTRIBUTE_STRUCTS - SMART
// 30-
for ( int iAttr = 0; iAttr < NUM_ATTRIBUTE_STRUCTS; iAttr++)
{
}
* This source code was highlighted with Source Code Highlighter .
しきい値( Threshold )を取得します。これは、属性を読み取る場合とほぼ同じ方法で行われます。 SENDCMDINPARAMS構造が読み込まれ 、2つのパラメーターが変更されます
cmdIn.cBufferSize = READ_THRESHOLD_BUFFER_SIZE;
cmdIn.irDriveRegs.bFeaturesReg = READ_THRESHOLDS;
//
BYTE bOutThresholds[ sizeof (SENDCMDOUTPARAMS) + READ_THRESHOLD_BUFFER_SIZE - 1] = {0};
bResult = DeviceIoControl(drive, SMART_RCV_DRIVE_DATA, &cmdIn, sizeof (cmdIn), bOutThresholds, sizeof (bOutThresholds), &dwReturn, NULL);
//
LPDRIVEATTRIBUTEHDR lpThrHdr = (LPDRIVEATTRIBUTEHDR)(((LPSENDCMDOUTPARAMS)bOutThresholds)->bBuffer);
LPATTRTHRESHOLD lpThresholds = (LPATTRTHRESHOLD)(lpThrHdr->bData);
// -
for ( int iAttr = 0; iAttr < NUM_ATTRIBUTE_STRUCTS; iAttr++)
{
}
* This source code was highlighted with Source Code Highlighter .
作業を簡単にするために、 CSMARTInfoクラスで情報をラップしました
// - SMART
typedef struct SMARTAttribute
{
int nId;
BYTE bValue;
BYTE bWorst;
BYTE bThreshold;
WORD wStatusFlags;
__int64 nRaw;
}
SMARTAttribute;
// SMART
class CSMARTInfo
{
public :
CSMARTInfo();
~CSMARTInfo();
public :
// ,
//
BOOL GetDriveModel( int nDrive, wstring &strModel);
// SMART
BOOL IsSmartSupported( int nDrive);
// SMART
BOOL EnableSmart( int nDrive);
//
BOOL GetInfo( int nDrive, GETVERSIONINPARAMS &info);
// SMART
BOOL GetAttributes( int nDrive, vector<SMARTAttribute> &attributes);
};
* This source code was highlighted with Source Code Highlighter .
SMARTを扱っている間、私は興味深い観察をしました。 標準標準ですが、属性の意味と目的、および異なるメーカーによる解釈は異なります。 たとえば、Seagateは、 生の読み取りエラーレート (ID = 0x1)およびシークエラーレート (ID = 0x7)属性の不気味で増え続ける値を示しています。 Seagateに関連してこれらのパラメーターに関する情報を見つけようとしましたが、Seagateフォーラムでのこのトピックに関するユーザーの投稿とそれらからの正解を除いて、何も見つかりませんでした。 すべてが正常であることをサポートし、そうでなければなりません。
SMARTを使用して、問題を診断および予測するだけでなく、たとえば、 電源オン時間属性(ID = 0x9、費やした時間数)またはデバイスの電源を入れ直したかどうかを確認することもできます。 カウント (ID = 0x0C、ディスクの完全なオン/オフサイクルの数)。 しかし、動作中にこのディスクがクラッシュしました(物理的に、床で)-属性G-senseエラー率 (0xBF、衝撃荷重に起因するエラーの数)