Skip to content

Repository files navigation

环形缓冲区 (Ring Buffer)

支持不定长数据项的轻量级C语言环形缓冲区实现,可直接存储结构体而无需序列化,适合嵌入式系统。当前版本 v1.2.0

✨ 核心特性

不定长 Item Size(主要特点)

与传统仅支持 uint8_t 的环形缓冲区不同,本库通过 item_size 参数支持任意大小的数据项

// ✅ 直接存储结构体,无需序列化
typedef struct { uint32_t ts; float temp; } SensorData;

static uint8_t buf[sizeof(SensorData) * 100];
static ringbuf_t rb = RINGBUFCRTL_INIT(buf, 100, sizeof(SensorData), false);

SensorData data = {...};
ringBuf_push(&rb, &data);  // 直接使用!

对比其他实现:

  • ❌ 大多数C实现:仅支持单字节,需手动序列化
  • ✅ FreeRTOS Queue:支持不定长,但需动态内存
  • 本库:不定长 + 零拷贝 + 无动态内存 + 类型安全

其他特性

  • 🚀 高性能索引:扩展索引范围(0~2*depth-1),减少取模运算约50%
  • 🔄 灵活模式:支持覆盖/非覆盖模式
  • 📦 批量操作:提供 push_multi / pop_multi API
  • 💾 零拷贝:使用用户提供的静态内存,无动态分配
  • 🔍 Peek 功能:支持按索引查看数据而不移除
  • 🧪 完整测试套件:包含多种使用场景的测试用例
  • 🛡️ 类型安全:使用专用类型别名(ringbuf_uidx_tringbuf_cnt_t 等),避免大深度缓冲区下的溢出风险
  • 参数校验RINGBUF_ARG_CHECK 宏统一校验 depth/item_size 非零及 2*depth 不溢出索引类型,所有 API 调用自动检查
  • 🔇 调试输出可完全关闭:组件内部打印 RING_DEBUG 默认关闭(构建时可选启用);DBG_macro.h 可通过 DBG_ENABLE=0 整体关闭,不引入 snprintf,降低小栈 MCU 上的栈与代码开销
  • 🔒 预留互斥锁接口:头文件中定义了 ringbuf_mutex_tringbuf_lock_func_tringbuf_unlock_func_t 类型,方便集成外部同步机制

⚠️ 重要提示

本项目仅针对裸机环境实现,未实现线程安全保护。

在RTOS或多线程环境中使用时,需外部添加互斥锁或临界区保护。

快速开始

#include "ringBuffer.h"

// 1. 定义数据类型和缓冲区
typedef struct { uint32_t ts; float value; } DataItem;
static uint8_t buf[sizeof(DataItem) * 50];
static ringbuf_t rb = RINGBUFCRTL_INIT(buf, 50, sizeof(DataItem), false);

int main(void) {
    ringBuf_init(&rb);
    
    // 2. 写入数据
    DataItem item = {.ts = 12345, .value = 25.5f};
    ringBuf_push(&rb, &item);
    
    // 3. 读取数据
    DataItem received;
    if (ringBuf_pop(&rb, &received) == RINGBUF_OK) {
        // 处理数据
    }
    
    return 0;
}

Peek 功能示例

// 查看指定位置的数据而不移除
DataItem peeked;
if (ringBuf_peek(&rb, &peeked, 0) == RINGBUF_OK) {
    // 查看第一个元素
}

// 批量查看多个元素
DataItem peekArray[3];
short peeked_count = 0;
ringBuf_peek_multi(&rb, peekArray, 3, 0, &peeked_count);

构建

mkdir build && cd build
cmake ..
cmake --build .

或在Windows上运行 build.bat

调试开关

开关 默认 说明
RINGBUF_RING_DEBUG (CMake) / -DRING_DEBUG OFF 启用组件内部调试打印(ringBuf_init 打印参数),会引入 snprintf
RINGBUF_DEMO_PRINTS=OFF (CMake) / -DDBG_ENABLE=0 ON 整体关闭 DBG_macro.h 打印宏:编译为空操作,不引入 <stdio.h>/snprintf,适用于小栈 MCU 发布构建
RINGBUF_ARG_CHECK=OFF (CMake) / -DRINGBUF_ARG_CHECK_ENABLE=0 ON 关闭 API 参数校验(指针 NULL 检查与 buffer/depth/item_size 配置校验),减小代码与运行时开销;关闭后非法入参将导致未定义行为,仅限调用者完全可信的发布构建

API 参考

函数 说明
ringBuf_init(rb) 初始化缓冲区
ringBuf_clear(rb) 清空缓冲区
ringBuf_push(rb, &data) 写入单个数据项
ringBuf_pop(rb, &data) 读取并移除
ringBuf_peek(rb, &data, index) 查看指定索引位置的数据但不移除
ringBuf_push_multi(rb, data, count, &written) 批量写入
ringBuf_pop_multi(rb, data, count, &read) 批量读取
ringBuf_peek_multi(rb, data, count, start_index, &peeked) 批量查看指定起始位置的数据
ringBuf_count(rb, &count) 获取当前数据项数量(通过指针返回)

返回值: 多数函数返回 RINGBUF_OK 表示成功,其他为错误码(RINGBUF_ERR_EMPTY, RINGBUF_ERR_WR_DENIED, RINGBUF_ERR_IDX 等)。ringBuf_count 通过 ringbuf_cnt_t *pCount 指针返回计数值。

技术亮点

  1. 扩展索引范围:索引范围 0~2*depth-1,取模频率降低50%
  2. 零拷贝设计:直接使用用户提供的静态内存
  3. 类型安全:专用类型别名(ringbuf_uidx_t/ringbuf_ucnt_t/ringbuf_idx_t/ringbuf_cnt_t)确保索引和计数变量类型一致
  4. 参数校验RINGBUF_ARG_CHECK 宏集中校验,覆盖所有 API 入口,防止 depth/item_size 为零或 2*depth 溢出索引类型
  5. 覆盖策略:可选覆盖模式(丢弃旧数据)或非覆盖模式(返回错误)
  6. Peek 功能:支持按索引查看数据而不影响读写指针
  7. 批量操作:高效的批量数据处理能力
  8. 互斥锁预留ringBuf_lock_func_t / ringBuf_unlock_func_t 函数指针类型,方便集成 RTOS 同步机制

完整API详见 ringBuffer.h

注意事项

  1. 使用前必须正确初始化环形缓冲区结构
  2. 确保传入的数据指针有效且具有足够空间
  3. 在中断服务程序中使用需特别注意重入问题
  4. 如需在多线程环境中使用,请添加适当的同步机制
  5. Peek 操作不会改变读写指针状态
  6. 批量操作会尽可能多地处理数据,即使部分失败也会返回已处理的数量

🛠 修复记录

  • v1.2.1 (2026-08-10):修复 _calc_count() 写指针折返后的计数错误。wr/rd 为未掩码 虚拟索引(范围 [0, 2*depth),折返边界在 2*depth),当 wr < rd(写指针已折返)时 条数应为 wr + 2*depth - rd,原实现误用 depth 折返,会少算 depth:满缓冲折返后 ringBuf_count 报 0、ringBuf_pop 误报 EMPTY,或下溢成负数导致满/空判定全乱(数据丢失)。 此修复不影响公开 API 签名,仅在折返路径修正计数。

许可证

本项目为学习用途,可根据需要自由使用和修改。

About

基于C实现的兼容不同item Size的环形缓冲区核心

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages