键值对存储 (KV)
概述
KV存储系统是YOC中一个以Key-Value方式进行持久化存储的轻量级组件,主要为基于nor flash的小型MCU设备提供通用的Key-Value持久化存储接口。该系统采用极小的代码及内存开销,支持断电保护、磨损均衡等功能。
KV存储系统支持只读模式与读写模式共存,只读模式可以用于工厂生产数据,读写模式可用于运行时的数据存储。
断电保护特性
断电保护的设计是为了在修改KV时,能保证KV不会被破坏的事务处理机制,即要写入失败,要么写入成功,对于已经存的KV,写失败后,KV的值仍然为旧值。对于不存在的KV,写失败后,KV不存在。
磨损均衡特性
在通常的应用中,部分KV被经常修改,由于FLASH物理特性,擦写的次数有一定的限制,擦写次数超过次数时,该块会损坏不能使用。磨损均衡的设计是将KV的写入分散到多 block上,避免存储在固定的位置上,达到磨损均衡的效果。磨损均衡主要依赖以下两个策略来实现:
异地更新策略
Key-Value键值对采用顺序写入、异地更新的方式,即不再在原存储位置擦除重写,而是在其余空闲位置写入新键值并将原键值标记无效等待回收。这样既可以减少flash的擦除操作次数,又可以提高flash的空间利用率,也避免了对“特定”存储区块过度使用的问题。
示意图如下:
垃圾回收策略
当free block总数接近gc下限时,会触发gc操作。flash数据在gc前,存在有效键值和无效键值交织的情况;gc后,把有效文件数据归并到free block,原区域则被擦除并置入free block。gc循环向后搬运键值。
示意图如下:
坏块处理特性
Nor flash有一定的擦写次数限制,如果达到这个限制,或者由于物理方面的损坏,会导致这些block写入有问题。KV系统采用直接片上链式读取,擦除与写入时校验数据正确性,不采用特殊的标识信息来处理坏块,当 block 擦除失败或者写失败后,会重新申请新的数据块,避免坏块被错误使用。
接口定义
初始化kv系统
int aos_kv_init(const char *partname)
参数
- partname:分区名称
返回值
- 0:成功
- -1:失败
初始化kv系统
int aos_kv_flash_init(const char *flashname, int addr, int block_num);
参数
- flashname:FLASH名称
- addr:起始地址
- block_num:块数目(KV项数目)
返回值
- 0:成功
- -1:失败
恢复kv初始化值
int aos_kv_reset(void)
参数
- 无
返回值
- 0:成功
- -1:失败
设置KV数据
若key不存在添加,已经存在进行覆盖
int aos_kv_set(const char *key, char *value, int len, int sync)
- 参数
- key:键值
- value:写入数据的缓存区
- len:写入数据长度
- sync:同步标识符,保留参数,请传入1
- 返回值
- 0:成功
- -1:失败
设置KV字符串数据
若key不存在添加,已经存在进行覆盖
int aos_kv_setstring(const char *key, const char *v);
- 参数
- key:键值
- v:写入的字符串
- 返回值
- 大于0:成功
- -1:失败
设置KV浮点数据
若key不存在添加,已经存在进行覆盖
int aos_kv_setfloat(const char *key, float v);
- 参数
- key:键值
- v:写入的浮点数据
- 返回值
- 0:成功
- -1:失败
设置KV整型数据
若key不存在添加,已经存在进行覆盖
int aos_kv_setint(const char *key, int v);
- 参数
- key:键值
- v:写入的整型数据
- 返回值
- 0:成功
- -1:失败
获取KV key键的数据
int aos_kv_get(const char *key, void *buffer, int *buffer_len);
- 参数
- key:键值
- buffer:读取数据的缓存区
- buffer_len:输入buffer长度,输出实际数据长度
- 返回值
- 0:成功
- -1:失败
获取KV key键的字符串数据
KV系统无类型标志,调用者需要确认读写类型对应
int aos_kv_getstring(const char *key, char *value, int len);
- 参数
- key:键值
- value:读取数据的缓存区
- len:缓存区长度,若长度小于实际数据长度,截断后返回
- 返回值
- 大于0:返回KV中数据的实际长度,若返回值大于等于len,说明数据还有未被读取
- 小于等于0:失败
获取KV key键的浮点数据
KV系统无类型标志,调用者需要确认读写类型对应
int aos_kv_getfloat(const char *key, float *value);
- 参数
- key:键值
- value:读取数据的缓存区
- 返回值
- 0:成功
- -1:失败
获取KV key键的整型数据
KV系统无类型标志,调用者需要确认读写类型对应
int aos_kv_getint(const char *key, int *value);
- 参数
- key:键值
- value:读取数据的缓存区
- 返回值
- 0:成功
- -1:失败
删除指定的KV数据
int aos_kv_del(const char *key);
- 参数
- key:键值
- 返回值
- 0:成功
- -1:失败