前言
- 为了方便阅读和调试单独抽离源文件
- 通过clion进行学习和分析
相关结构体
结构体
struct rt_ringbuffer {
rt_uint8_t *buffer_ptr; // 数据存放
rt_uint16_t read_mirror: 1; // 用于区分缓冲区状态
rt_uint16_t read_index: 15; // 读数据索引位置
rt_uint16_t write_mirror: 1; // 用于区分缓冲区状态
rt_uint16_t write_index: 15; // 写数据索引位置
rt_int16_t buffer_size; // 数据空间大小
};
枚举
enum rt_ringbuffer_state {
RT_RINGBUFFER_EMPTY, // 缓冲区为空
RT_RINGBUFFER_FULL, // 缓冲已满
RT_RINGBUFFER_HALFFULL, // 缓冲区(未满
};
相关函数
rt_ringbuffer_status(内联函数)
/**
*
* @param rb 环形缓冲区结构体
* @return 缓冲区状态
* RT_RINGBUFFER_EMPTY: 缓冲区为空
* RT_RINGBUFFER_FULL: 缓冲区满了
* RT_RINGBUFFER_HALFFULL: 缓冲区有数据,但没有满
*/
rt_inline enum rt_ringbuffer_state rt_ringbuffer_status(struct rt_ringbuffer *rb) {
// 判断读的索引位置和写的索引位置是否相等
if (rb->read_index == rb->write_index) {
// 判断读写标志位是否相等
if (rb->read_mirror == rb->write_mirror)
return RT_RINGBUFFER_EMPTY;
else
return RT_RINGBUFFER_FULL;
}
return RT_RINGBUFFER_HALFFULL;
}
rt_ringbuffer_data_len
声明
rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb)
定义
/**
* 获取环形缓冲区数据长度
* @param rb 环形缓冲区
* @return 环形缓冲区数据长度
*/
rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb) {
// 判断环形缓冲区的存储状态
switch (rt_ringbuffer_status(rb)) {
case RT_RINGBUFFER_EMPTY: // 缓冲区为空
return 0;
case RT_RINGBUFFER_FULL: // 缓冲区满了
return rb->buffer_size;
case RT_RINGBUFFER_HALFFULL: // 缓冲区有数据,但没有满
default:
// 判断当前读写索引的位置
if (rb->write_index > rb->read_index) // 写的位置大于读的位置,说明写的位置还没有去覆盖已经读的位置
return rb->write_index - rb->read_index;
else
return rb->buffer_size - (rb->read_index - rb->write_index); // 理解为总长-读取的索引+写的索引(覆盖的数量)
};
}
rt_ringbuffer_space_len (宏定义)
返回循环缓冲的空余空间大小
#define rt_ringbuffer_space_len(rb) ((rb)->buffer_size - rt_ringbuffer_data_len(rb))
rt_ringbuffer_init
声明
void rt_ringbuffer_init(struct rt_ringbuffer *rb, rt_uint8_t *pool, rt_int16_t size);
定义
/**
*
* @param rb 环形缓冲区结构体
* @param pool 缓冲区指针
* @param size pool 大小
*/
void rt_ringbuffer_init(struct rt_ringbuffer *rb,
rt_uint8_t *pool,
rt_int16_t size) {
// 参数校验
RT_ASSERT(rb != RT_NULL); // 检验结构体是否为空
RT_ASSERT(size > 0); // 检验缓冲区大小是否大于0
// 初始化读写索引和读写标志位->0
rb->read_mirror = rb->read_index = 0;
rb->write_mirror = rb->write_index = 0;
// 数据指针指向pool
rb->buffer_ptr = pool;
// 根据数据对齐返回对应的缓冲区大小,可能使用的空间会比size下
// 关系为 rb->buffer_size <= size
rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
}
rt_ringbuffer_put
声明
rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint16_t length)
定义
/**
* 通过此方法说明,当缓冲数据满的情况,想往里面写入数据是直接丢弃数据
* @param rb 环形缓冲区结构体
* @param ptr 写入数据
* @param length 写入长度
* @return 返回写入成功的长度; 一般可以与length进行对比,判断是否写入成功
*/
rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint16_t length) {
rt_uint16_t size;
// 环形缓冲区结构体不为空验证
RT_ASSERT(rb != RT_NULL);
/* 获取剩余空闲空间大小 */
size = rt_ringbuffer_space_len(rb);
/* 没有空间,直接返回 */
if (size == 0)
return 0;
// 剩余空间,不足,将写入的长度改为剩余空间的长度
if (size < length)
length = size;
// 如果总长-写入索引 > 要写入的长度: 说明不会出现覆盖数据的现象
if (rb->buffer_size - rb->write_index > length) {
/* read_index - write_index = empty space */
// 直接拷贝数据
memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
// 写入索引长度增加length
rb->write_index += length;
return length;
}
// 出现覆盖已经读取数据区域的情况
// 01 现将空余的地方进行写入
memcpy(&rb->buffer_ptr[rb->write_index],&ptr[0],rb->buffer_size - rb->write_index);
// 02 再将已经读取过数据的地方进行覆盖写入
memcpy(&rb->buffer_ptr[0],&ptr[rb->buffer_size - rb->write_index],length - (rb->buffer_size - rb->write_index));
/* we are going into the other side of the mirror */
// 03 写入的位置,从头开始,将标志位取反
rb->write_mirror = ~rb->write_mirror;
// 04 更新写入位置
rb->write_index = length - (rb->buffer_size - rb->write_index);
return length;
}
rt_ringbuffer_put_force
1、此函数rt_ringbuffer_put不同的地方就是,会覆盖原有的数据,保持新数据能添加
声明
rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb,const rt_uint8_t *ptr,rt_uint16_t length)
定义
/**
* 通过此方法说明,当缓冲数据满的情况,会覆盖原有的数据
* @param rb 环形缓冲区结构体
* @param ptr 写入数据
* @param length 写入的长度;
* @return
*/
rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb,const rt_uint8_t *ptr,rt_uint16_t length) {
rt_uint16_t space_length;
RT_ASSERT(rb != RT_NULL);
space_length = rt_ringbuffer_space_len(rb);
// 写入长度大于缓冲区长度,改变写入长度等于缓冲区长度
if (length > rb->buffer_size) {
ptr = &ptr[length - rb->buffer_size];
length = rb->buffer_size;
}
// 如果总长-写入索引 > 要写入的长度
if (rb->buffer_size - rb->write_index > length) {
/* read_index - write_index = empty space */
memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
rb->write_index += length;
// 如果写入长度大于空闲空间,直接让读取位置指向写入位置
if (length > space_length)
rb->read_index = rb->write_index;
return length;
}
memcpy(&rb->buffer_ptr[rb->write_index],
&ptr[0],
rb->buffer_size - rb->write_index);
memcpy(&rb->buffer_ptr[0],
&ptr[rb->buffer_size - rb->write_index],
length - (rb->buffer_size - rb->write_index));
/* we are going into the other side of the mirror */
rb->write_mirror = ~rb->write_mirror;
rb->write_index = length - (rb->buffer_size - rb->write_index);
if (length > space_length) {
rb->read_mirror = ~rb->read_mirror;
rb->read_index = rb->write_index;
}
return length;
}
rt_ringbuffer_get
声明
rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,rt_uint8_t *ptr,rt_uint16_t length)
定义
/**
* 从缓冲区获取数据
* @param rb
* @param ptr
* @param length
* @return 获取的实际长度
*/
rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,rt_uint8_t *ptr,rt_uint16_t length) {
rt_size_t size;
RT_ASSERT(rb != RT_NULL);
/* whether has enough data */
size = rt_ringbuffer_data_len(rb);
/* no data */
if (size == 0)
return 0;
/* less data */
if (size < length)
length = size;
if (rb->buffer_size - rb->read_index > length) {
/* copy all of data */
memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
rb->read_index += length;
return length;
}
memcpy(&ptr[0],
&rb->buffer_ptr[rb->read_index],
rb->buffer_size - rb->read_index);
memcpy(&ptr[rb->buffer_size - rb->read_index],
&rb->buffer_ptr[0],
length - (rb->buffer_size - rb->read_index));
/* we are going into the other side of the mirror */
rb->read_mirror = ~rb->read_mirror;
rb->read_index = length - (rb->buffer_size - rb->read_index);
return length;
}
剩余函数
都比较简单,请自行查看RT-Thread源码