新网站如何做流量,网站开发与实训报告,电商网站建设教案,网站底部悬浮代码wordpressUtils子系统是OpenHarmony的公共基础库#xff0c;存放OpenHarmony通用的基础组件。这些基础组件可被OpenHarmony各业务子系统及上层应用所使用。公共基础库在不同平台上提供的能力#xff1a;
LiteOS-M内核#xff1a;KV(key value)存储、文件操作、定时器、Dump系统属性。…Utils子系统是OpenHarmony的公共基础库存放OpenHarmony通用的基础组件。这些基础组件可被OpenHarmony各业务子系统及上层应用所使用。公共基础库在不同平台上提供的能力
LiteOS-M内核KV(key value)存储、文件操作、定时器、Dump系统属性。LiteOS-A内核KV(key value)存储、定时器、JS API(设备查询数据存储)、Dump系统属性。
本文介绍下移植开发板时如何适配utils子系统之KV存储部件并介绍下相关的运行机制原理。KV存储部件定义在utils\native\lite\。源代码目录如下
utils/native/lite/ # 公共基础库根目录
├── file # 文件接口实现
├── hals # HAL目录
│ └── file # 文件操作硬件抽象层头文件
├── include # 公共基础库对外接口文件
├── js # JS API目录
│ └── builtin
│ ├── common
│ ├── deviceinfokit # 设备信息Kit
│ ├── filekit # 文件Kit
│ └── kvstorekit # KV存储Kit
├── kal # KAL目录
│ └── timer # Timer的KAL实现
├── kv_store # KV存储实现
│ ├── innerkits # KV存储内部接口
│ └── src # KV存储源文件
├── memory
│ └── include # 内存池管理接口
├── os_dump # Dump系统属性
└── timer_task # Timer实现1、KV存储部件适配示例
1.1 配置产品解决方案config.json
utils子系统之KV存储部件的适配示例可以参考vendor\ohemu\qemu_csky_mini_system_demo\config.json代码片段如下。⑴处用于配置子系统的KV存储部件。⑵处指定在开发板目录中适配目录这个适配目录下需要创建目录device\qemu\SmartL_E802\adapter\hals\utils\file\之前的移植案例与原理文章中介绍过vendor_adapter_dir目录。对于KV存储部件与适配syspara_lite部件类似适配kv_store部件时键值对会写到文件中。在轻量系统中文件操作相关接口有POSIX接口与HalFiles接口这两套实现。部件文件utils\native\lite\kv_store\src\BUILD.gn中声明了enable_ohos_utils_native_lite_kv_store_use_posix_kv_api配置参数默认值为true。当使用默认值或主动设置为true时使用POSIX相关的接口否则使用HalFiles相关的接口。如果使用HalFiles相关的接口需要适配UtilsFile部件参考之前的移植案例与原理文章即可。 {subsystem: utils,components: [{ component: file, features:[] },
⑴ { component: kv_store, features:[] }]}],
⑵ vendor_adapter_dir: //device/qemu/SmartL_E802/adapter,1.2 适配后运行示例代码
适配后编写如下代码就可以使用KV存储功能。下面是示例代码程序片段实现保存键值通过key键获取对应的值删除键值等等。
// 存储/更新key对应数据项
const char key1[] key_sample;
const char defValue[] test case of key value store.;
int ret UtilsSetValue(key1, defValue);// 根据key获取对应数据项
char value1[32] {0};
ret UtilsGetValue(key1, value1, 32);// 删除key对应数据项
UtilsDeleteValue(key1);2、KV存储部件kvstore_common通用代码
2.1 结构体、函数声明、变量
在文件utils\native\lite\kv_store\src\kvstore_common\kvstore_common.h中声明了KV存储的函数并定义了结构体KvItem。⑴处定义了键值的最大长度⑵处的FEATURE_KV_CACHE宏开关定义在utils\native\lite\include\utils_config.h默认是定义了该宏的。⑶处定义的结构体成员包含键值以及前驱后继结构体指针。
⑴ #define MAX_KEY_LEN 32#define MAX_VALUE_LEN 128boolean IsValidChar(const char ch);boolean IsValidValue(const char* value, unsigned int len);boolean IsValidKey(const char* key);⑵ #ifdef FEATURE_KV_CACHE
⑶ typedef struct KvItem_ {char* key;char* value;struct KvItem_* next;struct KvItem_* prev;} KvItem;void DeleteKVCache(const char* key);void AddKVCache(const char* key, const char* value, boolean isNew);int GetValueByCache(const char* key, char* value, unsigned int maxLen);int ClearKVCacheInner(void);#endif在文件utils\native\lite\kv_store\src\kvstore_common\kvstore_common.c中定义了内部全局变量g_itemHeader、g_itemTail分别指向键值链表的首尾g_sum记录键值对数量。
#ifdef FEATURE_KV_CACHE
static KvItem* g_itemHeader NULL;
static KvItem* g_itemTail NULL;
static int g_sum 0;
#endif2.2 键值有效性判断函数
函数IsValidKey、IsValidValue分别用于判断键、值是否为有效的。⑴处表明键值必须为小写的字符数值下划线或者点符号。使用IsValidValue判断值是否有效时需要传入2个参数一个是要判断的字符串值的指针一个是长度len。⑵处获取字符串的个数包含最后的null不超过最大长度MAX_VALUE_LEN。然后进一步判断如果长度为0长度大于等于最大长度MAX_VALUE_LEN因为需要末尾的null等于也不行或者大于参数中传递的长度时都会返回FALSE否则返回TRUE。使用IsValidKey判断键是否有效时先调用函数IsValidValue确保长度是有效的然后调用函数IsValidChar判断每一个字符都是有效的只能是小写字符数值或者点符号。 boolean IsValidChar(const char ch){
⑴ if (islower(ch) || isdigit(ch) || (ch _) || (ch .)) {return TRUE;}return FALSE;}boolean IsValidValue(const char* value, unsigned int len){if (value NULL) {return FALSE;}
⑵ size_t valueLen strnlen(value, MAX_VALUE_LEN);if ((valueLen 0) || (valueLen MAX_VALUE_LEN) || (valueLen len)) {return FALSE;}return TRUE;}boolean IsValidKey(const char* key){if (!IsValidValue(key, MAX_KEY_LEN)) {return FALSE;}size_t keyLen strnlen(key, MAX_KEY_LEN);for (size_t i 0; i keyLen; i) {if (!IsValidChar(key[i])) {return FALSE;}}return TRUE;}2.3 根据键删除值DeleteKVCache
⑴处的函数FreeItem释放结构体成员变量指针结构体占用的内存。函数DeleteKVCache用于删除键参数对应的值。⑵处从键值对头部的第一个键值开始循环键值链表比对参数中的键和循环到的键。如果不相等则循环下一个链表节点。如果一直不相等并且循环到的节点为NULL说明链表中不存在相同的键直接返回不需要执行删除操作。如果执行到⑶说明键值对中存在匹配的键键值对总数减去1。⑷处对删键值后的数量的各种情况进行判断如果键值对数量为0键值对首尾指针设置为NULL;如果删除的是队首元素队尾元素队中元素分别处理。⑸处释放要删除的结构体占用的内存。
⑴ static void FreeItem(KvItem* item){if (item NULL) {return;}if (item-key ! NULL) {free(item-key);}if (item-value ! NULL) {free(item-value);}free(item);}void DeleteKVCache(const char* key){if (key NULL || g_itemHeader NULL) {return;}⑵ KvItem* item g_itemHeader;while (strcmp(key, item-key) ! 0) {item item-next;if (item NULL) {return;}}
⑶ g_sum--;
⑷ if (g_sum 0) {g_itemHeader NULL;g_itemTail NULL;} else if (item g_itemHeader) {g_itemHeader item-next;g_itemHeader-prev NULL;} else if (item g_itemTail) {g_itemTail item-prev;g_itemTail-next NULL;} else {item-prev-next item-next;item-next-prev item-prev;}
⑸ FreeItem(item);}2.4 添加缓存AddKVCache
函数AddKVCache添加一对键值到缓存里。共三个参数前两者为键和值第三个参数boolean isNew为true时会先尝试删除旧的键值对只保留最新的键值数据。如果为false可能存在键值相同的两个键值对但是值不同。做完必要的参数非空校验后执行⑴获取键、值的字符长度。⑵处处理是否删除旧的键值对数据。⑶处为键值对结构体申请内存区域内存区域置空。⑷处为键、值分别申请内存区域申请的时候多加1个字符长度用于保存null空字符。⑸处把参数传入的键值数据复制到键值对结构体对应的内存区域。⑹处理缓存内没有键值数据的情况。当缓存有键值信息时新加入的放入键值对链表头部。⑻处当缓存数量大于最大缓存数时依次从尾部删除。
void AddKVCache(const char* key, const char* value, boolean isNew)
{if (key NULL || value NULL) {return;}⑴ size_t keyLen strnlen(key, MAX_KEY_LEN);size_t valueLen strnlen(value, MAX_VALUE_LEN);if ((keyLen MAX_KEY_LEN) || (valueLen MAX_VALUE_LEN)) {return;}
⑵ if (isNew) {DeleteKVCache(key);}
⑶ KvItem* item (KvItem *)malloc(sizeof(KvItem));if (item NULL) {return;}(void)memset_s(item, sizeof(KvItem), 0, sizeof(KvItem));
⑷ item-key (char *)malloc(keyLen 1);item-value (char *)malloc(valueLen 1);if ((item-key NULL) || (item-value NULL)) {FreeItem(item);return;}
⑸ if ((strcpy_s(item-key, keyLen 1, key) ! EOK) ||(strcpy_s(item-value, valueLen 1, value) ! EOK)) {FreeItem(item);return;}item-prev NULL;item-next NULL;
⑹ if (g_itemHeader NULL) {g_itemHeader item;g_itemTail item;g_sum;return;}
⑺ item-next g_itemHeader;g_itemHeader-prev item;g_itemHeader item;g_sum;
⑻ while (g_sum MAX_CACHE_SIZE) {KvItem* needDel g_itemTail;g_itemTail g_itemTail-prev;FreeItem(needDel);g_itemTail-next NULL;g_sum--;}
}2.5 从缓存中获取值GetValueByCache
函数GetValueByCache用于从缓存中读取值。共三个参数前两者为键和值const char* ke为键输入参数char* value为输出参数用于保存返回的值第三个参数unsigned int maxLen用于限制获取的值的最大长度。该函数的返回值代表获取成功EC_SUCCESS或失败EC_FAILURE。做完必要的参数非空校验后执行⑴循环键值对链表获取对应键的键值结构体。如果获取不到则返回EC_FAILURE否则执行⑵获取值的长度当这个长度超出值的最大长度时返回EC_FAILURE。⑶处如果获取的值的长度超出参数传入的长度不会截断而是返回错误。从item-value把值复制到输出参数里如果失败也会返回错误。
int GetValueByCache(const char* key, char* value, unsigned int maxLen)
{if (key NULL || value NULL || g_itemHeader NULL) {return EC_FAILURE;}KvItem* item g_itemHeader;
⑴ while (strcmp(key, item-key) ! 0) {item item-next;if (item NULL) {return EC_FAILURE;}}
⑵ size_t valueLen strnlen(item-value, MAX_VALUE_LEN);if (valueLen MAX_VALUE_LEN) {return EC_FAILURE;}
⑶ if ((valueLen maxLen) || (strcpy_s(value, maxLen, item-value) ! EOK)) {return EC_FAILURE;}return EC_SUCCESS;
}2.6 清除缓存ClearKVCacheInner
清除缓存函数ClearKVCacheInner会把缓存的键值对全部清空返回清除成功或失败的返回值。⑴如果键值对链表头节点为空返回成功。⑵处循环键值对链表每一个键值对元素一一删除。每删除一个执行⑶把基础缓存的键值对数目减1。
int ClearKVCacheInner(void)
{
⑴ if (g_itemHeader NULL) {return EC_SUCCESS;}KvItem* item g_itemHeader;
⑵ while (item ! NULL) {KvItem* temp item;item item-next;FreeItem(temp);
⑶ g_sum--;}g_itemHeader NULL;g_itemTail NULL;return (g_sum ! 0) ? EC_FAILURE : EC_SUCCESS;
}如果大家想更加深入的学习 OpenHarmony 开发的内容不妨可以参考以下相关学习文档进行学习助你快速提升自己
OpenHarmony 开发环境搭建https://qr18.cn/CgxrRy 《OpenHarmony源码解析》https://qr18.cn/CgxrRy
搭建开发环境Windows 开发环境的搭建Ubuntu 开发环境搭建Linux 与 Windows 之间的文件共享……
系统架构分析https://qr18.cn/CgxrRy
构建子系统启动流程子系统分布式任务调度子系统分布式通信子系统驱动子系统…… OpenHarmony 设备开发学习手册https://qr18.cn/CgxrRy OpenHarmony面试题内含参考答案https://qr18.cn/CgxrRy 写在最后
如果你觉得这篇内容对你还蛮有帮助我想邀请你帮我三个小忙点赞转发有你们的 『点赞和评论』才是我创造的动力。关注小编同时可以期待后续文章ing不定期分享原创知识。想要获取更多完整鸿蒙最新学习资源请移步前往小编https://qr21.cn/FV7h05