实现linux硬盘smart检测

devtools/2025/1/17 18:25:19/

一、下载交叉编译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)

常用的接口还有获取硬盘温度、使用时长、获取硬盘容量等。


http://www.ppmy.cn/devtools/151330.html

相关文章

【Linux】9.Linux第一个小程序进度条

文章目录 Linux第一个小程序&#xff0d;进度条相关知识创建程序1. 程序原理2. 基础程序原理实现 井号进度条代码实现箭头进度条代码实现多重进度条代码实现 Linux第一个小程序&#xff0d;进度条 相关知识 特殊符号&#xff1a; $ 和 $^ 回车换行&#xff1a; 回车和换行其实…

C++ union 联合(八股总结)

union&#xff08;联合体&#xff09;允许在同一内存位置上存储不同的数据类型&#xff0c;所有成员共享相同的内存空间。 内存布局 由于联合体的所有成员都共享同一块内存&#xff0c;因此联合体的大小是其最大成员的大小。联合体的实际大小取决于其最大成员的类型和对齐要求…

高性能计算服务器是指什么?

高性能计算服务器是一种具有高网络传输速度、快速极端和高速存储功能的服务器&#xff0c;高性能服务器还采用了先进的硬件技术和优化的软件配置&#xff0c;为企业和用户提供更快的响应时间和更高的并发处理能力&#xff0c;一般会用于处理大规模数据和复杂的计算任务当中。 本…

Spring Boot 下的Swagger 3.0 与 Swagger 2.0 的详细对比

先说结论&#xff1a; Swgger 3.0 与Swagger 2.0 区别很大&#xff0c;Swagger3.0用了最新的注释实现更强大的功能&#xff0c;同时使得代码更优雅。 就个人而言&#xff0c;如果新项目推荐使用Swgger 3.0&#xff0c;对于工具而言新的一定比旧的好&#xff1b;对接于旧项目原…

销售团队如何选择销售业绩统计表模板?

在销售团队中&#xff0c;统计和分析业绩是日常工作的重要部分。比如&#xff0c;通过统计表&#xff0c;我们可以看到上个月各销售员的成交额&#xff0c;了解哪些产品受欢迎&#xff0c;哪些区域市场潜力大。这不仅帮助我们回顾过往表现&#xff0c;还能为未来决策提供依据。…

链表 -- 反转链表,k个一组翻转链表,两两交换链表中结点

目录 反转链表 题目 ​编辑 分析 代码 k个一组翻转链表 题目 分析 代码 两两交换链表中的结点 题目 ​编辑 分析 代码 反转链表 题目 分析 反转过程: newhead作为遍历指针,最终停在尾结点上prev保存上一个结点,通过改变newhead和prev的连接来实现反转(核心)通过ne…

Kubernetes 部署 RabbitMQ 集群教程

本文介绍如何在 Kubernetes 中部署 RabbitMQ 集群&#xff0c;包含从命名空间创建到配置 NFS 存储的详细步骤。 参考文档&#xff1a; RabbitMQ 集群部署NFS StorageClass 创建 部署步骤 1. 创建命名空间 kubectl create ns rabbitmq2. 创建 RBAC 权限 创建文件 rabbitmq…

力扣 394. 字符串解码

&#x1f517; https://leetcode.cn/problems/decode-string 题目 对字符串中的 k[s] 解码为 s 重复 k 次 思路 碰到数字&#xff0c;开始进行递归 decode 展开&#xff0c;否则字符不解码针对于解码的部分&#xff0c;先明确 k 的数字是多少&#xff0c;再明确 [ ] 括号中…