一、下载交叉编译libatasmart库
下载链接:https://www.linuxfromscratch.org/blfs/view/svn/general/libatasmart.html
libatasmart库编译依赖libudev库,交叉编译器前先准备依赖的libudev:
设置libudev的环境变量,并通过configure编译文件生成库和头文件
export PKG_CONFIG_PATH=${PWD}/../../libeudev/build/lib/pkgconfig:$PKG_CONFIG_PATH
./configure --prefix=${PWD}/../build CC=aarch64-buildroot-linux-gnu-gcc --host=aarch64-buildroot-linux-gnu- --disable-static
make & make install
生成的库和头文件如图:
接下来只需要把库和头文件添加到cmake工程中,就可以使用了:
二、libatasmart使用
只有一个头文件atasmart.h,包含了所有的接口,接下来介绍一些常用的接口:
1、启动smart自检
int sk_disk_smart_self_test(SkDisk *d, SkSmartSelfTest test);
SkDisk *d 要操作的硬盘对象 这个是通过sk_disk_open(const char *name, SkDisk **d)获取的
SkSmartSelfTest test smart自检类型
typedef enum SkSmartSelfTest {
SK_SMART_SELF_TEST_SHORT = 1, //启动短时间的自检
SK_SMART_SELF_TEST_EXTENDED = 2,//启动扩展(长时间)自检
SK_SMART_SELF_TEST_CONVEYANCE = 3,//启动运输自检
SK_SMART_SELF_TEST_ABORT = 127//终止当前的自检
} SkSmartSelfTest;
2、获取smart属性表
int sk_disk_smart_parse_attributes(SkDisk *d, SkSmartAttributeParseCallback cb, void* userdata);
SkDisk *d 操作的硬盘对象
SkSmartAttributeParseCallback cb 回调函数指针, 处理每个解析后的 SMART 属性的回调函数。
原型格式:
typedef void (*SkSmartAttributeParseCallback)(SkDisk *d, const SkSmartAttributeParsedData *a, void* userdata);
d
:指向 SkSmartAttributeParsedData
的指针,包含一个 SMART 属性的解析结果。
userdata
:用户自定义的数据,直接传递到回调函数中
void* userdata 用户自定义数据,用于传递到回调函数中。
使用实例:
sk_disk_smart_parse_attributes(
pDisk,
[](SkDisk* _, SkSmartAttributeParsedData const* pData, void* pUserdata)
{
auto attribute = reinterpret_cast<std::vector<Attribute >*>(pUserdata);
Attribute attr = {};
/* 获取属性表*/
attr.id = pData->id;
attr.name = pData->name;
attr.flags = pData->flags;
attr.current = pData->current_value;
attr.worst = pData->worst_value;
attr.threshold = pData->threshold;
for (auto i = 0;i < 6; ++i)
{
attr.raw += pData->raw[i] << (8 * i);
}
attribute->push_back(attr);
},
&attribute);
属性类定义:
class Attribute
{
public:
uint8_t id; // 属性 ID,表示具体的 SMART 属性编号
std::string name; // 属性名称,表示该属性的具体含义(如 "Temperature")
uint8_t current; // 当前值,表示该属性的当前状态
uint8_t worst; // 最差值,表示该属性历史上的最差状态
uint8_t threshold; // 阈值,当属性值低于此值时可能意味着问题
uint64_t raw; // 原始数据,包含更详细的低级信息(通常以十六进制显示)
uint16_t flags; // 属性标志,描述该属性的特性(如是否关键)
};
3、获取硬盘的整体评估状态
int sk_disk_smart_get_overall(SkDisk *d, SkSmartOverall *overall);
SkDisk *d 要操作的硬盘对象
SkSmartOverall *overall 磁盘的整体健康状态
typedef enum SkSmartOverall {
SK_SMART_OVERALL_GOOD, // 磁盘健康状态良好
SK_SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST, // 过去至少有一个预失效属性超过了阈值
SK_SMART_OVERALL_BAD_SECTOR, // 当前至少有一个坏扇区
SK_SMART_OVERALL_BAD_ATTRIBUTE_NOW, // 当前至少有一个预失效属性超过了阈值
SK_SMART_OVERALL_BAD_SECTOR_MANY, // 当前存在多个坏扇区
SK_SMART_OVERALL_BAD_STATUS, // 磁盘自检报告评估为负面
_SK_SMART_OVERALL_MAX // 枚举值的最大标记(内部使用)
} SkSmartOverall;
举例,根据overall大致可以分为三个状态:
switch(overall)
{
case SK_SMART_OVERALL_GOOD:
log_info("硬盘整体评估良好");
stSmartDetection.enAllAssessment = System::AllAssessment_E::WELL;
break;
case SK_SMART_OVERALL_BAD_SECTOR:
case SK_SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST:
log_info("存在少量坏扇区");
stSmartDetection.enAllAssessment = System::AllAssessment_E::EXIST_BAD;
break;
case SK_SMART_OVERALL_BAD_ATTRIBUTE_NOW:
case SK_SMART_OVERALL_BAD_SECTOR_MANY:
case SK_SMART_OVERALL_BAD_STATUS:
log_info("故障即将发生");
stSmartDetection.enAllAssessment = System::AllAssessment_E::FAIILURE;
break;
default:
break;
}
4、 解析磁盘的 SMART 数据
int sk_disk_smart_parse(SkDisk *d, const SkSmartParsedData **data);
SkDisk *d 要操作的硬盘对象
const SkSmartParsedData **data 解析后的 SMART 数据
typedef struct SkSmartParsedData {
/* 动态数据 (Volatile data) */
// 离线数据收集的当前状态,指示离线健康检查是否正在进行、已完成或出现错误。
SkSmartOfflineDataCollectionStatus offline_data_collection_status;
// 离线数据收集的累计时间(秒),表示磁盘已经花费的时间来完成健康检查。
unsigned total_offline_data_collection_seconds;
// 自检执行状态,指示当前自检操作的状态,例如运行中、成功完成或失败。
SkSmartSelfTestExecutionStatus self_test_execution_status;
// 自检剩余百分比,表示当前运行的自检任务还需要完成的百分比。
unsigned self_test_execution_percent_remaining;
/* 固定数据 (Fixed data) */
// 是否支持短时测试和扩展测试,使用布尔值表示(1 = 支持,0 = 不支持)。
SkBool short_and_extended_test_available : 1;
// 是否支持传输测试(Conveyance Test),用于检测传输过程中的损伤。
SkBool conveyance_test_available : 1;
// 是否支持启动测试功能。
SkBool start_test_available : 1;
// 是否支持中止测试功能。
SkBool abort_test_available : 1;
// 短时测试所需的时间(分钟),即运行短时健康检查的预期时间。
unsigned short_test_polling_minutes;
// 扩展测试所需的时间(分钟),即运行完整健康检查的预期时间。
unsigned extended_test_polling_minutes;
// 传输测试所需的时间(分钟),即运行传输过程健康检查的预期时间。
unsigned conveyance_test_polling_minutes;
} SkSmartParsedData;
在调用这个接口前需要先用sk_disk_smart_read_data读取smart数据
sk_disk_smart_read_data (pDisk)
解析数据,比如获取自检状态:
switch(pData->self_test_execution_status)
常用的接口还有获取硬盘温度、使用时长、获取硬盘容量等。