編輯語:
晶片開放社群(OCC)面向開發者推出RISC-V系列内容,通過多角度、全方位解讀RISC-V,系統性梳理總結相關理論知識,建構RISC-V知識圖譜,促進開發者對RISC-V生态全貌的了解。
為了幫助廣大開發者快速上手YoC基礎軟體平台,實作RISC-V生态應用的極簡開發,我們推出了YoC元件介紹系列内容,并向大家介紹了其中的
CSI元件、
AT元件 AV(多媒體)元件和
PARTITION元件。本期我們将為大家講解YoC的KV元件,通過KV元件的簡介、設計概述、主要原理描述以及示例四部分内容,帶大家全面了解該元件。
01 介紹
KV是基于Nor Flash的一種Key-Value 資料存儲系統,該系統采用極小的代碼及記憶體開銷(最小資源 rom:3K bytes,ram:100bytes),在小規模的Nor Flash上實作資料的存儲管理能力,支援斷電保護、磨損均衡、壞塊處理等功能,并提供标準的aos kv接口進行通路。
KV 存儲系統支援隻讀模式與讀寫模式共存,隻讀模式可以用于工廠生産資料,讀寫模式可用于運作時的資料存儲。
02 設計概述
2.1 資料格式
為了簡化設計,降低複雜性,減少代碼規模及記憶體開銷,又考慮到隻讀KV與讀寫KV的相容性,KV系統未采用傳統KV系統或檔案系統中采用的HEAD描述結構,采用的鍊式周遊方式設計。
根據FLASH 的特點,以block 為機關,每一個block 都是一個獨立的存儲單元,限制一個KV必須存儲在一個block上。
KV格式:
- 隻讀:=\n
- 讀寫:<key><\0><size_lo><size_hi><version>=<value><size_hi><erase_flag>
如下表
位元組數 | n | 1 | 4 | ||||||
字段 | KEY | SIZE_LO | SIZE_HI | VERSION | = | VALUE | ERASE FLAG |
- 字段具體說明
空間(Byte) | 說明 | |
使用者傳入的key,由字母、數字等可列印字元組成 | ||
0位 | 數值0的特殊值,緊跟在KEY後,是檢索的關鍵标記值 | |
SIZE_LO/ | 2 | 占兩個位元組,儲存KEY的長度與Value的長度,Value占高10位,KEY占低6位(允許最大KEY長度為63位元組,Value理論長度為1023,但由到block 的大小限制,最大長度不得超出block)SIZE_LO為value 長度的低8位,SIZE_HI 的低2位為value 長度的高2位 |
Version | 版本,用于儲存KEY被修改的次數,當一個KV被多次修改時,Version最累加,累加到255時掉頭為1;該字元用于保證KV修改的有效性,在寫入時斷電可能會造成KV的重複,采用最新版本的KV為有效KV,删除曆史版本的KV; | |
等号位 | 即字元”c”,占位及檢索标記位,用于識别有效KV | |
Value | 使用者傳入的value值,長度由實際Value 長度決定,受block 及 key 長度限制 | |
/ | 儲存上述SIZE_HI 資料,該位用于校檢KV的有效性 | |
Erase flag | KV删除标記位,由四個位元組組成,非0時為有效KV,為0時,表示該KV已被删除 |
2.2 重點功能設計概述
2.2.1 斷電保護
斷電保護的設計是為了在修改KV時,能保證KV不會被破壞的事務處理機制,即要寫入失敗,要麼寫入成功,對于已經存的KV,寫失敗後,KV的值仍然為舊值。對于不存在的KV,寫失敗後,KV不存在。
2.2.2 磨損均衡
在通常的應用中,部分KV被經常修改,由于FLASH實體特性,擦寫的次數有一定的限制,擦寫次數超過次數時,該塊會損壞不能使用。磨損均衡的設計是将KV的寫入分散到多 block上,避免存儲在固定的位置上,達到磨損均衡的效果。磨損均衡主要依賴以下兩個政策來實作:
- 異地更新政策 Key-Value鍵值對采用順序寫入、異地更新的方式,即不再在原存儲位置擦除重寫,而是在其餘空閑位置寫入新鍵值并将原鍵值标記無效等待回收。這樣既可以減少flash的擦除操作次數,又可以提高flash的空間使用率,也避免了對“特定”存儲區塊過度使用的問題。
- 垃圾回收政策 當free block總數接近gc下限時,會觸發gc操作。flash資料在gc前,存在有效鍵值和無效鍵值交織的情況;gc後,把有效檔案資料歸并到free block,原區域則被擦除并置入free block。gc循環向後搬運鍵值。
2.2.3 壞塊處理
Nor flash有一定的擦寫次數限制,如果達到這個限制,或者由于實體方面的損壞,會導緻這些block寫入有問題。KV系統采用直接片上鍊式讀取,擦除與寫入時校驗資料正确性,不采用特殊的辨別資訊來處理壞塊,當block 擦除失敗或者寫失敗後,會重新申請新的資料塊,避免壞塊被錯誤使用。
03 主要原理描述
3.1 關鍵過程處理流程
- 格式化
将所有塊擦除後,若擦除失敗則置為壞塊。
- 初始化
周遊整個系統,統計每個block 上KV的個數、占用空間、可用位置,删除KV的數量,清理無效的KV,回收無用的block,若cache功能打開,則還會将所有key資訊存入cache中。
- 寫鍵值
3.1 查找系統中是否已存在該鍵值
3.2 配置設定新的kvnode,計算版本号、長度,将kvnode 寫入block
3.3 删除已存在的鍵值
- 讀取及删除鍵值
4.1 查找系統中是否已存在該鍵值
4.2 讀取或删除已存在的鍵值
3.2 GC處理流程
當free block總數接近gc下限時,會觸發gc操作。如下圖,flash資料在gc前,存在有效鍵值和無效鍵值交織的情況;gc後,把有效檔案資料歸并到free block,原區域則被擦除并置入free block。gc循環向後搬運鍵值

3.3 CACHE功能
對于資源相對豐富的晶片,可以通過打開在package.yaml中配置CONFIG_KV_ENABLE_CACHE來打開cache功能,cache打開後,KV初始化時會統一将所有key的資訊存儲到cache中,之後的讀寫删等操作通過cache可快速定位到flash上的位置,減少對flash的周遊操作,進而可提升讀速率30%,寫速率95%,删除速率50%。
04 示例
#include <aos/kv.h>
void kv_test(void)
{
int ret =aos_kv_init("kv"); //初始化kv,注意需要将partition先處理化
if (ret != 0) {
printf("kv init failed");
return;
}
aos_kv_set("test_key", "hello"); //向kv裡寫入"hello"
char buffer[6];
aos_kv_get("test_key", buffer, 6); //從kv裡讀取資料到buffer
printf("kv read: %s\r\n", buffer);
}
05 下期預告
本文是YoC元件介紹系列的完結篇,下期内容将為大家講解如何上傳元件到OCC進行開源。歡迎大家持續關注RISC-V系列内容。