当前位置: 首页 > news >正文

【编程】-环形缓冲区

环形缓冲区(Ring Buffer/Circular Buffer)详解
环形缓冲区是一种首尾相连的线性数据结构,通过固定大小的数组模拟循环存储,是嵌入式、实时系统中的核心数据结构之一。它的设计目标是高效处理数据流,避免动态内存分配,保证确定性操作时间(O(1)复杂度)。

  1. 核心特点
    固定容量:预分配固定大小的数组,避免运行时内存分配。

循环写入:当数据填满缓冲区时,覆盖最旧的数据(或阻塞)。

无内存拷贝:通过移动头尾指针(或索引)管理数据,无需搬移元素。

线程安全:单生产者单消费者(SPSC)场景下可无锁实现。

  1. 典型应用场景
    (1)数据流缓冲(高频场景)
    串口/UART通信
    接收不定长数据包时,环形缓冲区作为硬件中断和主程序间的桥梁:

c
// 中断服务程序(ISR)快速写入
void UART_ISR() {
ring_buffer_push(&uart_rx_buf, UART_DR); // 写入接收到的字节
}

// 主程序异步读取
void process_data() {
uint8_t byte;
while (ring_buffer_pop(&uart_rx_buf, &byte)) {
decode_packet(byte); // 处理数据
}
}
音频处理
音频采集(生产者)和播放(消费者)速度可能不一致,环形缓冲区平滑数据流:

text
麦克风 → [环形缓冲区] → 扬声器
(2)高实时性系统
RTOS任务间通信
在FreeRTOS中,xQueue 的底层可能使用环形缓冲区传递消息。

DMA传输
DMA控制器直接读写环形缓冲区,减少CPU干预(如ADC连续采样)。

(3)日志记录
嵌入式日志系统
在内存受限时,环形缓冲区存储最新日志,满时覆盖旧记录:

c
log_buffer_write(“Sensor error: %d”, err_code); // 写入日志
// 日志满时自动覆盖最旧条目
(4)网络数据包处理
以太网/Wi-Fi数据帧缓冲
网卡驱动将收到的数据包存入环形缓冲区,协议栈逐包取出解析。

  1. 代码实现(C语言示例)
    基础实现(无锁SPSC)
    c
    typedef struct {
    uint8_t *buffer; // 存储区指针
    size_t head; // 写入位置
    size_t tail; // 读取位置
    size_t capacity; // 缓冲区大小
    } ring_buffer_t;

// 初始化
void ring_buffer_init(ring_buffer_t *rb, uint8_t *pool, size_t size) {
rb->buffer = pool;
rb->capacity = size;
rb->head = rb->tail = 0;
}

// 写入数据(返回是否成功)
bool ring_buffer_push(ring_buffer_t *rb, uint8_t data) {
size_t next_head = (rb->head + 1) % rb->capacity;
if (next_head == rb->tail) return false; // 缓冲区满
rb->buffer[rb->head] = data;
rb->head = next_head;
return true;
}

// 读取数据(返回是否成功)
bool ring_buffer_pop(ring_buffer_t *rb, uint8_t *data) {
if (rb->tail == rb->head) return false; // 缓冲区空
*data = rb->buffer[rb->tail];
rb->tail = (rb->tail + 1) % rb->capacity;
return true;
}
优化技巧
内存对齐:根据CPU架构对齐缓冲区(如32字节对齐加速DMA访问)。

位掩模替代取模:若缓冲区大小为2的幂次,用 & (size - 1) 替代 % 提升速度。

原子操作:多线程环境下,使用 stdatomic.h 保护 head 和 tail。

  1. 环形缓冲区 vs 其他数据结构
    场景 环形缓冲区优势 替代方案
    高频数据流 O(1)操作,无动态内存分配 链表(内存碎片风险)
    实时性要求高 确定性延迟,适合中断上下文 动态队列(延迟不可控)
    内存受限 预分配固定大小,无额外开销 动态数组(可能扩容)
    单生产者单消费者 可无锁实现 需加锁的队列
  2. 常见问题与解决方案
    Q1:缓冲区满时如何处理?
    策略1:阻塞生产者(如RTOS中触发任务切换)。

策略2:丢弃最旧数据(适合实时传感器流)。

策略3:动态扩容


文章转载自:
http://brimless.zzyjnl.cn
http://antiperiodic.zzyjnl.cn
http://biltong.zzyjnl.cn
http://alure.zzyjnl.cn
http://ascribable.zzyjnl.cn
http://cardioscope.zzyjnl.cn
http://authentication.zzyjnl.cn
http://calipee.zzyjnl.cn
http://ampul.zzyjnl.cn
http://argentous.zzyjnl.cn
http://charger.zzyjnl.cn
http://argot.zzyjnl.cn
http://academgorodok.zzyjnl.cn
http://amdg.zzyjnl.cn
http://arty.zzyjnl.cn
http://bisexual.zzyjnl.cn
http://biscuit.zzyjnl.cn
http://beth.zzyjnl.cn
http://belittle.zzyjnl.cn
http://atishoo.zzyjnl.cn
http://blueprint.zzyjnl.cn
http://browbeat.zzyjnl.cn
http://aril.zzyjnl.cn
http://befriend.zzyjnl.cn
http://anthropotomy.zzyjnl.cn
http://antitrinitarian.zzyjnl.cn
http://apogee.zzyjnl.cn
http://brigandage.zzyjnl.cn
http://attrited.zzyjnl.cn
http://atmolysis.zzyjnl.cn
http://www.dtcms.com/a/280665.html

相关文章:

  • 安全参綉25暑假第一次作业
  • 超详细 anji-captcha滑块验证uniapp微信小程序前端组件
  • 备忘录设计模式
  • asyncio 与 uvloop
  • 策略设计模式分析
  • 如何将华为文件传输到电脑
  • Linux的用户和用户组与权限解析、环境变量说明与配置、sudo配置解析和使用
  • HarmonyOS从入门到精通:自定义组件开发指南(七):自定义事件与回调
  • 涨停板池,跌停板池,炸板池,次新股池,强势股池数据接口
  • 单臂路由实现VLAN互通实验
  • e签宝电子合同成为白象食品数字化转型中的关键一环
  • PostgreSQL 超详细安装与使用教程:从入门到实战
  • 深入剖析 React Server Components:原理、应用与性能优势
  • 设计模式一: 模板方法模式 (Template Method Pattern)
  • Nexus 私服管理工具
  • 李宏毅《生成式人工智能导论》 | 第11讲-第14讲:大型语言模型的可解释性、能力评估、安全性
  • 20250715问答课题-基于BERT与混合检索问答系统
  • 电商缓存强一致方案:数据库锁保障
  • 设计模式开篇:设计模式的七大核心原则
  • kube-proxy 中 IPVS 与 iptables
  • PyTorch笔记7----------计算机视觉基础
  • OpenCV 伽马校正函数gammaCorrection()
  • MODIS_Landsat_Sentinel2星源分幅简述【20250715】
  • 视频编码中熵编码之基于上下文的变长编码(Huffman霍夫曼编码和指数哥伦布)
  • 【YOLOv11-目标检测】06-模型部署(C++)
  • 06_pt-table-sync 工具解决 MySQL 主从数据不一致
  • conda环境保存(后期再来整理)
  • etcd自动压缩清理
  • 2-Nodejs运行JS代码
  • iOS高级开发工程师面试——Swift