天天看點

AliOS-Things KV分析AliOS-Things KV分析

AliOS-Things KV分析

1 簡介

KV元件寫平衡特性的實作考量

由于小型物聯網嵌入式裝置的硬體資源較為匮乏,對code size以及RAM的占用size比較敏感。是以基于資源消耗的考量,寫平衡特性在KV元件中的實作遵循make it simple原則,主要依賴以下兩個政策來實作:

  1. 異地更新政策:Key-Value鍵值對采用順序寫入、異地更新的方式,即不再在原存儲位置擦除重寫,而是在其餘空閑位置寫入新鍵值并将原鍵值标記無效等待回收。這樣既可以減少flash的擦除操作次數,又可以提高flash的空間使用率,也避免了對“特定”存儲區塊過度使用的問題。示意圖如下:
    AliOS-Things KV分析AliOS-Things KV分析
  2. 垃圾回收政策:當flash存儲區塊的剩餘可用空間達到門檻值時,會觸發垃圾回收機制。垃圾回收機制采用基礎的SGC算法進行資源回收釋放,即當系統觸發垃圾回收時,從目前寫入塊的下一個存儲塊開始依次檢查存儲塊的管理狀态,若存儲塊的管理狀态為Dirty狀态,則将該存儲塊中的有效資料依次挪向垃圾回收預留的空閑存儲塊,當資料遷移完成後,會擦除Dirty存儲塊并标記可用空閑狀态。
    AliOS-Things KV分析AliOS-Things KV分析

2 使用

在developer中kv對外提供了3個接口 :

  • aos_kv_set:添加資料
  • aos_kv_get:擷取資料
  • aos_kv_del:删除資料

以上轉載自:AliOS Things KV元件的寫平衡特性

3 源碼分析

以aos_kv_set為例,進行簡單的分析。

aos_kv_set:

int aos_kv_set(const char *key, const void *val, int len, int sync)
{
    kv_item_t *item;
    int        ret;
    // 資料有效驗證
    if (!key || !val || len <= 0 || strlen(key) > ITEM_MAX_KEY_LEN ||
        len > ITEM_MAX_VAL_LEN) {
        return RES_INVALID_PARAM;
    }
	// The flag to indicate garbage collection is triggered
    if (g_kv_mgr.gc_triggered) {
        (g_kv_mgr.gc_waiter)++;
        aos_sem_wait(&(g_kv_mgr.gc_sem), AOS_WAIT_FOREVER);
    }
	// 擷取鎖
    if ((ret = aos_mutex_lock(&(g_kv_mgr.kv_mutex), AOS_WAIT_FOREVER)) !=
        RES_OK) {
        return ret;
    }

    item = kv_item_get(key);
    if (item) {  /* 已經存在,則更新,否則增加一個key-value*/
        ret = kv_item_update(item, key, val, len);
        kv_item_free(item);
    } else {
        ret = kv_item_store(key, val, len, 0);
    }
	// 執行完畢,釋放鎖
    aos_mutex_unlock(&(g_kv_mgr.kv_mutex));
    return ret;
}
           

如果滿足條件,則執行kv_item_store對資料進行儲存

kv_item_store:

static int kv_item_store(const char *key, const void *val, int len,
                         uint16_t origin_off)
{
    kv_storeage_t store;
    item_hdr_t    hdr;
    char *        p;
    kvpos_t       pos;
    uint8_t       index;

    hdr.magic      = ITEM_MAGIC_NUM;
    hdr.state      = ITEM_STATE_NORMAL;
    hdr.key_len    = strlen(key);
    hdr.val_len    = len;
    hdr.origin_off = origin_off;

    store.len =
      (ITEM_HEADER_SIZE + hdr.key_len + hdr.val_len + ~KV_ALIGN_MASK) &
      KV_ALIGN_MASK;
    store.p = (char *)aos_malloc(store.len);
    if (!store.p) {
        return RES_MALLOC_FAILED;
    }

    memset(store.p, 0, store.len);
    p = store.p + ITEM_HEADER_SIZE;
    memcpy(p, key, hdr.key_len);
    p += hdr.key_len;
    memcpy(p, val, hdr.val_len);
    p -= hdr.key_len;
    hdr.crc = utils_crc8((uint8_t *)p, hdr.key_len + hdr.val_len);
    memcpy(store.p, &hdr, ITEM_HEADER_SIZE);

    pos = kv_item_calc_pos(store.len); /* 擷取要寫入的位址,并且啟動垃圾回收政策 */
    if (pos > 0) {
        // 寫到flash
        store.ret = raw_write(pos, store.p, store.len);
        if (store.ret == RES_OK) {
            g_kv_mgr.write_pos = pos + store.len;
            index              = g_kv_mgr.write_pos >> BLK_BITS;
            g_kv_mgr.block_info[index].space -= store.len;
        }
    } else {
        store.ret = RES_NO_SPACE;
    }

    if (store.p) {
        aos_free(store.p);
    }
    return store.ret;
}
           

參考

  • AliOS Things KV元件的寫平衡特性

繼續閱讀