FlashDB 在嵌入式系统中占用硬件资源

lashDB支持两种模式:FAL模式和文件模式。FAL模式用于嵌入式系统直接操作闪存,而文件模式可能在操作系统上使用文件模拟闪存。这种分层设计使得FlashDB可以灵活适应不同环境。

FlashDB 是一个为嵌入式系统设计的轻量级键值(KV)和时间序列(TS)数据库库,支持 Flash 存储。以下是实现方法详解:

1. 架构设计

FlashDB 采用模块化分层设计,核心分为 接口层存储引擎层底层驱动层

  • 接口层 :提供 KVDB 和 TSDB 的 API,如 fdb_kv_setfdb_tsl_append

  • 存储引擎层:实现数据存储逻辑,包括状态管理、垃圾回收(GC)、缓存机制。

  • 底层驱动层:通过 FAL 或文件系统抽象 Flash 操作,实现跨平台兼容。


2. 关键数据结构

2.1 数据库基类 (struct fdb_db)
  • 作用:所有数据库类型(KVDB/TSDB)的基类。

  • 核心成员

struct fdb_db {

const char *name; // 数据库名称

fdb_db_type type; // 类型: FDB_DB_TYPE_KV 或 FDB_DB_TYPE_TS

union {

const char *dir; // 文件模式下的目录路径

fal_partition_t part; // FAL模式下的分区指针

} storage;

uint32_t sec_size; // 扇区大小(字节)

uint32_t max_size; // 数据库最大容量

bool init_ok; // 初始化标记

bool file_mode; // 是否为文件模式

// 锁函数指针,用户需实现

void (*lock)(fdb_db_t db);

void (*unlock)(fdb_db_t db);

};

2.2 键值数据库 (struct fdb_kvdb)
  • 继承自 fdb_db,扩展 KV 相关功能:

    struct fdb_kvdb {

    struct fdb_db parent; // 继承基类

    struct fdb_default_kv default_kvs; // 默认键值对

    bool gc_request; // GC 请求标志

    struct fdb_kv cur_kv; // 当前操作的 KV

    struct kvdb_sec_info cur_sector; // 当前扇区信息

    // 缓存优化

    struct kv_cache_node kv_cache_table[FDB_KV_CACHE_TABLE_SIZE];

    struct kvdb_sec_info sector_cache_table[FDB_SECTOR_CACHE_TABLE_SIZE];

    };

2.3 时间序列数据库 (struct fdb_tsdb)
  • 继承自 fdb_db,扩展时间序列功能:

    struct fdb_tsdb {

    struct fdb_db parent; // 继承基类

    struct tsdb_sec_info cur_sec; // 当前扇区信息

    fdb_time_t last_time; // 最后记录时间

    fdb_get_time get_time; // 时间获取回调函数

    size_t max_len; // 单条日志最大长度

    bool rollover; // 是否启用滚动覆盖

    };


3. 存储管理

3.1 扇区与状态管理
  • 扇区状态 :每个扇区通过状态表(status_table)记录存储状态(如 FDB_SECTOR_STORE_USING)和脏标记(如 FDB_SECTOR_DIRTY_TRUE)。

  • 状态操作

    // 设置状态位(如标记为已使用)

    size_t _fdb_set_status(uint8_t status_table[], size_t status_num, size_t status_index);

    // 获取当前状态

    size_t _fdb_get_status(uint8_t status_table[], size_t status_num);

3.2 数据持久化
  • 写入流程

    1. 预写状态 :标记为 FDB_KV_PRE_WRITE,防止写入中断导致数据损坏。

    2. 写入数据 :调用 _fdb_flash_write 写入键值对。

    3. 提交状态 :更新为 FDB_KV_WRITE

  • 原子性保障:通过状态机确保操作原子性,崩溃恢复时根据状态回滚。


4. 缓存机制

4.1 KV 缓存 (kv_cache_table)
  • LRU 策略 :通过 active 字段记录访问频度,淘汰最少使用的缓存项。

  • 快速查找:根据键名 CRC 快速定位缓存,减少 Flash 扫描。

4.2 扇区缓存 (sector_cache_table)
  • 缓存热点扇区:存储频繁访问的扇区信息,加速扇区状态查询。

5. 垃圾回收 (GC)

  • 触发条件:空间不足或手动调用 GC。

  • GC 流程

    1. 标记无效数据:遍历扇区,标记已删除的 KV。

    2. 迁移有效数据:将有效数据复制到新扇区。

    3. 擦除旧扇区:释放空间,更新元数据。


6. 文件模式实现

6.1 文件操作抽象
  • POSIX/LIBC 适配

    #ifdef FDB_USING_FILE_POSIX_MODE

    #define FDB_FILE_OPEN(path) open(path, O_RDWR | O_CREAT, 0666)

    #else

    #define FDB_FILE_OPEN(path) fopen(path, "rb+")

    #endif

  • 扇区文件管理 :每个扇区对应一个文件,文件名基于扇区地址生成(如 sec_0x0000.bin)。

6.2 文件缓存优化
  • 打开文件缓存 :通过 cur_file 数组缓存最近访问的文件句柄,减少频繁打开关闭。

7. 时间序列数据库特性

7.1 滚动覆盖 (Rollover)
  • 启用时:当存储空间满时,覆盖最旧数据。

  • 索引管理 :通过 end_idxstart_time 快速定位数据范围。

7.2 时间范围查询
  • 高效遍历

    void fdb_tsl_iter_by_time(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_cb cb, void *cb_arg);

    利用时间有序存储特性,二分查找快速定位时间窗口。


8. 错误处理与日志

  • 错误码 :定义 fdb_err_t 枚举,如 FDB_READ_ERRFDB_SAVED_FULL

  • 日志分级

    #define FDB_DEBUG(...) // 调试信息(条件编译控制)

    #define FDB_INFO(...) // 运行信息(始终输出)


9. 示例:KVDB 初始化与使用

#include <flashdb.h>

// 定义默认 KV

static struct fdb_default_kv_node default_kv_table[] = {

{"username", "armink", 0},

{"password", "123456", 0},

};

static struct fdb_default_kv default_kv = {

.kvs = default_kv_table,

.num = 2,

};

int main() {

fdb_kvdb_t kvdb = malloc(sizeof(struct fdb_kvdb));

// 初始化 KVDB(FAL 模式)

fdb_err_t err = fdb_kvdb_init(kvdb, "env", "kvdb_partition", &default_kv, NULL);

if (err != FDB_NO_ERR) {

FDB_INFO("KVDB init failed!\n");

return -1;

}

// 设置键值

fdb_kv_set(kvdb, "status", "ready");

// 读取键值

char *value = fdb_kv_get(kvdb, "status");

FDB_INFO("status: %s\n", value);

// 反初始化

fdb_kvdb_deinit(kvdb);

return 0;

}


10. 关键设计亮点

  • 跨平台适配:通过 FAL 和文件模式支持裸机与 OS 环境。

  • 数据完整性:CRC 校验 + 状态机确保崩溃恢复。

  • 空间高效:GC 机制 + 对齐写入减少碎片。

  • 性能优化:缓存 + 时间序列索引加速查询。

FlashDB 通过以上设计,在资源受限的嵌入式系统中实现了高效可靠的数据存储,适用于 IoT 设备、穿戴设备等场景。

FlashDB 作为专为嵌入式设计的轻量级数据库,其资源占用高度依赖配置和硬件环境。以下是关键资源消耗点及典型场景下的估算:


1. 内存占用 (RAM)

模块 典型配置 RAM 占用估算 说明
KV 缓存表 FDB_KV_CACHE_TABLE_SIZE=64 512 字节 每个条目 kv_cache_node 占 8 字节(CRC16 + active + 地址)
扇区缓存表 FDB_SECTOR_CACHE_TABLE_SIZE=8 1 KB 每个 kvdb_sec_info 结构约 128 字节
TSDB 元数据 单扇区存储 128 字节/扇区 tsdb_sec_info 结构存储时间戳和索引信息
运行时栈 基本操作 1~2 KB 函数调用栈,依赖递归深度和日志长度

总 RAM 消耗

  • 最小配置 (禁用缓存):约 1~2 KB

  • 典型配置 (启用缓存):约 2~4 KB

  • 高性能配置 (大缓存):可超过 10 KB


2. 存储占用 (Flash/EEPROM)

模块 典型场景 Flash 占用估算 说明
KVDB 元数据 每扇区头信息 32 字节/扇区 包含 magic、状态、剩余空间等
TSDB 元数据 每扇区头信息 48 字节/扇区 含时间戳、索引范围等
单条 KV 记录 Key="temp", Value=25.5 50~100 字节 含头部(状态、CRC、长度) + 键值数据(对齐损耗)
单条 TSL 记录 时间戳 + 温度数据 20~64 字节 含时间戳、状态、数据长度(依赖 max_len 配置)

示例容量规划

  • 小型设备 (4 KB Flash):支持约 20~50 条 KV100~200 条 TSL

  • 中型设备 (64 KB Flash):可管理 500+ KV5000+ TSL

  • 损耗均衡 :建议预留 10~20% 空间以降低 GC 频率


3. CPU 开销

操作 时间消耗 说明
KV 写入 5~50 ms 依赖 Flash 擦除时间(如 STM32F1 SPI Flash 擦除 4KB 约 40ms)
TSL 追加 1~10 ms 无擦除操作时较快,仅写入数据
GC 过程 100 ms~2 s 全扇区迁移时较长,建议在低负载时触发
KV 查询 0.1~5 ms 缓存命中时极快,未命中需遍历 Flash

4. 配置优化建议

降低资源占用的配置

// fdb_cfg.h

#define FDB_KV_CACHE_TABLE_SIZE 0 // 禁用 KV 缓存

#define FDB_SECTOR_CACHE_TABLE_SIZE 0 // 禁用扇区缓存

#define FDB_WRITE_GRAN 8 // 适配 Flash 最小写入单位(如 NOR Flash)

#define FDB_USING_TIMESTAMP_32BIT // 使用 32 位时间戳(节省 4 字节/记录)

提升性能的配置

// fdb_cfg.h

#define FDB_KV_CACHE_TABLE_SIZE 128 // 大缓存加速查询

#define FDB_SECTOR_CACHE_TABLE_SIZE 16 // 缓存更多扇区信息

#define FDB_USING_FAST_CRC32 // 启用硬件 CRC 加速校验


5. 对比其他嵌入式存储方案

方案 RAM 占用 Flash 占用 特性
FlashDB 2~10 KB 低~中等 轻量、支持 KV+TS、崩溃安全
SPIFFS 1~4 KB 高(块管理开销大) 类文件系统,适合大文件存储
EEPROM 0 按需使用 无磨损均衡,适合低频小数据
SQLite 50~200 KB 高(代码体积大) 完整 SQL 支持,适合复杂查询

6. 实际项目案例

智能家居温控器
  • 硬件:STM32F103 (64 KB Flash, 20 KB RAM)

  • 需求:存储 10 个参数(KV) + 每 5 分钟记录温度(TSL,保存 7 天)

  • FlashDB 配置

    • KVDB: 2 扇区(8 KB), 缓存 16 条目

    • TSDB: 24 扇区(48 KB), 支持滚动覆盖

  • 资源占用

    • RAM: 3.2 KB(缓存 + 运行时)

    • Flash: 56 KB(数据 + 元数据)

    • CPU: 每日 GC 约 200 ms


总结

  • 最低配置 :可运行在 < 2 KB RAM + 4 KB Flash 的 Cortex-M0 设备

  • 灵活扩展 :通过调整缓存和扇区数量适配从 8 位 MCULinux 嵌入式设备

  • 适用场景:IoT 传感器、穿戴设备、工控参数存储等对资源敏感的实时系统

相关推荐
虔城散人4 小时前
C语言 |位域结构体
c语言
Susea&4 小时前
数据结构初阶:队列
c语言·开发语言·数据结构
GOTXX4 小时前
【Qt】Qt Creator开发基础:项目创建、界面解析与核心概念入门
开发语言·数据库·c++·qt·图形渲染·图形化界面·qt新手入门
猿小喵4 小时前
记录一次TDSQL网关夯住故障
运维·数据库·mysql
电商api接口开发4 小时前
如何在C#中使用LINQ对数据库进行查询操作?
数据库·c#·linq
hnsqls4 小时前
Redis 常问知识
数据库·redis·缓存
序属秋秋秋5 小时前
算法基础_数据结构【单链表 + 双链表 + 栈 + 队列 + 单调栈 + 单调队列】
c语言·数据结构·c++·算法
王鑫的博客8865 小时前
本地git操作
c语言·git
经年小栈6 小时前
性能优化-Spring参数配置、数据库连接参数配置、JVM调优
数据库·spring·性能优化
mldl_6 小时前
(个人题解)第十六届蓝桥杯大赛软件赛省赛C/C++ 研究生组
c语言·c++·蓝桥杯