环形缓冲区的概念
环形缓冲区(Circular Buffer)是一种固定大小的数据结构,其存储空间首尾相连,形成逻辑上的环形。当数据到达缓冲区末尾时,会从头部开始继续写入,从而实现高效的数据循环存储。常用于数据流处理、生产者-消费者模型等场景。
环形缓冲区的特点
- 固定容量:缓冲区大小预先分配,无法动态扩展。
- 高效读写:通过移动指针(非数据搬移)实现O(1)时间复杂度的插入和删除。
- 覆盖策略:当缓冲区满时,可选择覆盖旧数据或拒绝新数据。
环形缓冲区的实现关键
- 读写指针:
- 写指针(head):指向下一个可写入的位置。
- 读指针(tail):指向下一个可读取的位置。
- 空/满判断:
- 空条件:读指针与写指针重合。
- 满条件:写指针的下一个位置是读指针(需预留一个位置区分空和满)
-
#ifndef ___RINGBUFFER_H__ #define ___RINGBUFFER_H__ #include "main.h" #include "string.h" #define RINGBUFFER_SIZE 30 typedef struct { uint32_t w;//写指针 uint32_t r;//读指针 uint8_t buffer[RINGBUFFER_SIZE]; uint32_t itemCount;//项目计数 }ringbuffer_t; void ringbuffer_init(ringbuffer_t *rb); uint8_t ringbuffer_is_full(ringbuffer_t *rb); uint8_t ringbuffer_is_empty(ringbuffer_t *rb); int8_t ringbuffer_write(ringbuffer_t *rb,uint8_t *data,uint32_t num); int8_t ringbuffer_read(ringbuffer_t *rb,uint8_t *data,uint32_t num); #endif
-
-
/*初始化环形缓冲区*/ void ringbuffer_init(ringbuffer_t *rb) { //设置读指针和写指针初始值为0 rb->r = 0; rb->w = 0; memset(rb->buffer,0,sizeof(uint8_t)*RINGBUFFER_SIZE);//将缓冲区内存清零 rb->itemCount = 0;//初始化项目计数为0 } /*检查环形缓冲区是否已满*/ uint8_t ringbuffer_is_full(ringbuffer_t *rb) { //如果项目计数等于缓冲区大小,返回1(已满),否则返回0(未满) return (rb->itemCount == RINGBUFFER_SIZE); } /*检查环形缓冲区是否为空*/ uint8_t ringbuffer_is_empty(ringbuffer_t *rb) { // 如果项目计数为0,返回1(为空),否则返回0(非空) return (rb->itemCount == 0); } /*向环形缓冲区写入数据*/ int8_t ringbuffer_write(ringbuffer_t *rb,uint8_t *data,uint32_t num) { //如果缓冲区已满,返回-1 if(ringbuffer_is_full(rb)) return -1; //将数据写入缓冲区 while(num--) { rb->buffer[rb->w] = *data++;//写入数据并移动写指针 rb->w = (rb->w + 1) % RINGBUFFER_SIZE;//写指针循环递增 rb->itemCount++;//增加项目计数 } return 0;//写入成功返回0 } /*从环形缓冲区读取数据*/ int8_t ringbuffer_read(ringbuffer_t *rb,uint8_t *data,uint32_t num) { //如果缓冲区为空,返回-1 if(ringbuffer_is_empty(rb)) return -1; //从缓冲区读取数据 while(num--) { *data++ = rb->buffer[rb->r];//读取数据并移动读指针 rb->r = (rb->r + 1) % RINGBUFFER_SIZE;//读指针循环递增 rb->itemCount--;//减少项目计数 } return 0;//读取成功返回0 }
此代码适用于裸机开发,使用操作系统时,存在缺陷。
-