Получаем атрибуты S.M.A.R.T

    S.M.A.R.T это технология оценки состояния жесткого диска, помогающая оценить текущее состояние и предсказать возможные проблемы и выход устройства из строя. Атрибуты S.M.A.R.T условно можно разделить на две группы: параметры, отражающие процесс изнашивания (старения) диска и текущие параметры (например, параметры производительности).

    Каждый атрибут имеет идентификатор, тип (критический, показатель производительности, счетчик ошибок, счетчик событий), текущее значение, пороговое значение (если текущее меньше порогового — начинайте искать новый диск), самое низкое, зафиксированное, значение атрибута. Описание каждого атрибута можно посмотреть здесь.

    На этом теоретическая часть заканчивается, перейдем к практике. Напишем программу, которая будет считывать и отображать атрибуты S.M.A.R.T. Скачать готовую программу с исходниками можно здесь.



    Для начала определим структуры, в которые мы будем получать интересующую нас информацию:
    // Заголовок атрибутов
    typedef struct _DRIVEATTRIBUTEHDR
    {
        // Номер версии
        WORD    wRevision;
        // Данные
        BYTE    bData[1];
    }
    DRIVEATTRIBUTEHDR, *PDRIVEATTRIBUTEHDR, *LPDRIVEATTRIBUTEHDR;

    // атрибут S.M.A.R.T
    typedef struct _DRIVEATTRIBUTE
    {
        // Идентификатор атрибута
        BYTE    bAttrID;
        // Тип атрибута (критический, счетчик ошибок и т.д.)
        WORD    wStatusFlags;
        // Значение атрибута
        BYTE    bAttrValue;
        // Худшее, зафиксированное, значение
        BYTE    bWorstValue;
        // Значение атрибута, ненормализованное
        BYTE    bRawValue[6];
        BYTE    bReserved;
    }
    DRIVEATTRIBUTE, *PDRIVEATTRIBUTE, *LPDRIVEATTRIBUTE;

    // Пареметр Threshold (пороговое значение) атрибута S.M.A.R.T
    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.

    Здесь 0 в "\\\\.\\PHYSICALDRIVE0" означает номер физического диска в системе.

    После получения дескриптора необходимо заполнить структуру 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 - максимально возможное количество атрибутов S.M.A.R.T
    // в настоящий момент равняется 30-ти
    for(int iAttr = 0; iAttr < NUM_ATTRIBUTE_STRUCTS; iAttr++)
    {
    }


    * This source code was highlighted with Source Code Highlighter.

    Получим пороговые значения (Threshold), делается это почти так же, как и в случае чтение атрибутов. Заполняется структура SENDCMDINPARAMS, меняются два параметра

    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
    // Структура-обертка для S.M.A.R.T атрибута
    typedef struct SMARTAttribute
    {
        int nId;

        BYTE bValue;
        BYTE bWorst;
        BYTE bThreshold;

        WORD wStatusFlags;

        __int64    nRaw;
    }
    SMARTAttribute;

    // Класс для работы со S.M.A.R.T
    class CSMARTInfo
    {
    public:
        CSMARTInfo();
        ~CSMARTInfo();

    public:
        // Вспомогательная функция, возвращающая
        // название модели жесткого диска
        BOOL GetDriveModel(int nDrive, wstring &strModel);

        // Поддерживается ли S.M.A.R.T на указанном диске
        BOOL IsSmartSupported(int nDrive);
        // Включить S.M.A.R.T на указанном диске
        BOOL EnableSmart(int nDrive);

        // Получить информацию о диске
        BOOL GetInfo(int nDrive, GETVERSIONINPARAMS &info);
        // Получить S.M.A.R.T атрибуты
        BOOL GetAttributes(int nDrive, vector<SMARTAttribute> &attributes);
    };


    * This source code was highlighted with Source Code Highlighter.


    Пока я разбирался со S.M.A.R.T сделал интересное наблюдение. Стандарт-стандартом, а вот значение и предназначение атрибутов, так же как и их трактовка у различных производителей своя. Например мой Seagate показывает жуткое, постоянно увеличивающееся, значение атрибутов Raw Read Error Rate (ID = 0x1) и Seek Error Rate (ID = 0x7). Я попытался найти информацию об этих параметрах применительно к Seagate, но так ничего и не нашел, не считая сообщений пользователей на данную тему на форуме Seagate и заверетильные ответы тех. поддержки, что все нормально, так должно и быть.

    Использовать S.M.A.R.T можно не только для диагностики и предсказания проблем, но и, например, для проверки — а не б\у ли мы купили, атрибут Power-On Hours (ID=0х9, число часов, проведенных во включенном состоянии) или Device Power Cycle Count (ID=0x0C, количество полных циклов включения-выключения диска). А не падал ли этот диск в процессе работы (в смысле физически, на пол) — атрибут G-sense error rate (0хBF, количество ошибок, возникающих в результате ударных нагрузок)
    Поделиться публикацией

    Похожие публикации

    Комментарии 43
      +1
      Очень интересная статья, спасибо!
        +2
        Спасибо за статью, особенно за последний абзац. Как то о такой возможности не задумывался, а нада было иногда…
          0
          Интересно, спасибо за статью!
            0
            спасибо за написанное приложение. сам малость кривоват в создании подобного.
            пойду проверять диски:)
              +1
              А как же быть с рейд массивами?
                0
                А что с RAID-массивами?
                Массивы состоят из отдельных дисков, в дисках есть SMART.
                  0
                  это верно, но на практике посмотреть подробные сведения SMART в массивах если и возможно, то с большим геморроем и не для всех контроллеров.
                0
                Спасибо… полезная штука Я пользуюсь похожей программой hard drive inspector
                  0
                  Кстати под Wine запускается но ничего не показывает. (Ubuntu 9.10)
                    0
                    С убунтой все проще значительно там велик уже изобретен… конкретно в 9,10 Palimpsest 2.28.0 (alt+F2 -> palimpsest)

                    Что касается последнего абзаца особенно улыбают диски хитачи… Количество перераспределенных секторов у меня на одном из ноутов первалило за 3кк… Странно но винт живой, я так пнимаю это со статистикой от производителя приколы…
                      0
                      Даже диски не отображает?
                        0
                        у меня на семерке тоже пустое окно
                          0
                          Попробуйте запустить с правами администратора.
                            0
                            все никак к семерке не привыкну
                        +1
                        smartctl под убунтой есть, ровно как и smartd, который будет делать всё втихую и отправлять в случае чего уведомление на мыло.
                          0
                          https://help.ubuntu.com/community/Smartmontools
                          0
                          Все отлично, но жаль нельзя увеличить окошко программы.
                            0
                            Исправил, перезалил
                              0
                              Спасибо!
                              Сейчас просто шикарно стало.
                            0
                            интересная вещица, спасибо!
                            вот только мой рэйд не хочет видеть (
                              0
                              Насчет рейдов пока ничего не нашел. Даже намеков.
                              0
                              У меня вот что =( Может не правильный хард?

                                0
                                WD120 — это IDE, его вообще не показывает. А WD320 — SATA, но на википедии не нашел описания даным параметрам.
                                  0
                                  Да и в описании атрибутов на сайте WD таких нет. А какая ОСь?
                                    0
                                    XP SP3
                                      0
                                      При чем как я тут посмотрел ключи дуюлируются, я так понимаю выводится инфа о двух хардах? Тоесть не под каждым хардом своя инфа, а под всеми вся. Жаль, лучше погрупировать, что б понятнее было к какому харду какой параметр относится.
                                        0
                                        И еще одно, каждый раз когда запускаю програму, каждый раз показывает другие ключи, какбудто оно по рандому их выводит =)) Если нужно могу отправить на почту скрины, что б не захламлять комменты.
                                          0
                                          Для начала попробую сам проверить на машине с двумя винтами, возможно в коде поселился какой-нибудь баг :)
                                    0
                                    Ах, какая жесть! А в винде нет что-то типа
                                    # smartctl -a /dev/sda

                                    ?
                                      0
                                      ага — есть. smartctl называется.
                                        0
                                        И зачем эти миллионы строчек кода?
                                          +1
                                          Топик не даром создан в разделе «Разработка». Строчки кода на тот случай, если Вам вдруг занадобится встроить в свою программу чтение S.M.A.R.T атрибутов.
                                            0
                                            Пропарсить табличку никак?
                                              +3
                                              Не изобретая велосипеды — вы никогда не сможете изобрести велосипед, который был бы лучше существующих!
                                                0
                                                Вы как нельзя точно передали мою мысль :)
                                                0
                                                Создать пайп, создать процесс, перенаправить вывод процесса в пайп, распарсить вывод… По моему уж лучше так, как в статье.
                                                  +1
                                                  Это ж одна строка :)
                                                    0
                                                    Ну, опять же, смотря где :)
                                        0

                                        Да с Сегейтами похоже беда — диски с разными датами покупки — хоть и одинаковые — но некоторые показания явно неправильные (например 1-5 вряд ли могут быть одинаковыми с такой точностью).
                                        P.S А где показания описанные в последнем абзаце?
                                          0
                                          Note that Seagate drives often report a raw value that is very high even on new drives, and does not thereby indicate a failure.
                                          en.wikipedia.org/wiki/S.M.A.R.T.
                                          0
                                          Запустил программу, и пустота… винт Samsung 160 IDE
                                            0
                                            Хммм надо было запустить от Администратора… странно, что сразу не выдало ошибку, что нужны права эти…
                                            –1
                                            Что-то пиздит Ваша прога.

                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                            Самое читаемое