ringbuf数据结构:
typedef struct quec_ring_buf_struct {
unsigned int size;
unsigned int rpos;
unsigned int wpos;
unsigned char *data;
}quec_ring_buf_t;
- rpos,指向待读取数据的起始位置
- wpos,指向下一个可写入数据的位置
- data,存储数据的内存空间,
- size,环形buf大小,大小常设为2的幂以优化取模运算
读写机制
- 写入数据:数据从wpos位置插入,wpos递增(以32位unsigned int为例,超过4294967295则 回绕到0),但要保证wpos-rpos要小于size。否则旧数据被覆盖丢失
- 读取数据:数据从rpos位置取出,rpos递增(以32位unsigned int为例,超过4294967295则 回绕到0)
- 关键逻辑:通过rpos、wpos索引形成环形
如何理解这个ringbuf,举个例子:w和r两个人在环形操场上跑步,操场长度为4294967295米,w在前面跑,r在后面追。w和r要遵守两个规则,w不能领先r size的长度,r不能超越w.
他们俩就这样一直跑着跑着,像CPU一样永不停歇.....
代码实现实例
创建
quec_ring_buf_t *__kfifo_rb_create(unsigned int size)
{
quec_ring_buf_t *rb = NULL;
if (size <= 0) {
return NULL;
}
rb = malloc(sizeof(quec_ring_buf_t));
if (NULL == rb) {
return NULL;
}
memset(rb, 0, sizeof(quec_ring_buf_t));
rb->data = malloc(size);
memset(rb->data, 0, size);
if (NULL == rb->data) {
free(rb);
return NULL;
}
rb->size = size;
return rb;
}
销毁
void __kfifo_rb_destroy(quec_ring_buf_t **rb)
{
if (*rb) {
if ((*rb)->data) {
free((*rb)->data);
(*rb)->data = NULL;
}
free(*rb);
*rb = NULL;
}
}
读操作
unsigned int __kfifo_rb_read(quec_ring_buf_t *rb, unsigned char *data, unsigned int len)
{
unsigned int r_size = 0, r_free_size = 0;
unsigned int r_data_len = 0;
if (!rb || !data || (len <= 0)) {
//quec_log("%s,rb=%#x,data=%#x,len=%d",__func__,rb,data,len);
return 0;
}
/*以下操作rb禁止被抢占,否则会导致其他任务获取的读写指针不是实时的,所以这里暂时将抢占优先级抬到0*/
quec_rtos_task_sched_lock();
r_data_len = __kfifo_rb_data_len(rb);
r_size = len < r_data_len ? len : r_data_len;
/* first get the data from ring_buf->read_pos until the end of the buffer */
r_free_size = r_size < (rb->size-(rb->rpos&(rb->size-1))) ? r_size : (rb->size-(rb->rpos&(rb->size-1)));
memcpy(data, rb->data+(rb->rpos&(rb->size-1)), r_free_size);
/* then get the rest (if any) from the beginning of the buffer */
memcpy(data+r_free_size, rb->data, r_size-r_free_size);
rb->rpos += r_size;
quec_rtos_task_sched_unlock();
return r_size;
}
写操作
unsigned int __kfifo_rb_write(quec_ring_buf_t *rb, unsigned char *data, unsigned int len)
{
unsigned int w_size = 0, w_free_size = 0;
unsigned int r_free_size = 0;
if (!rb || !data || (len <= 0)) {
//quec_log("%s,rb=%#x,data=%#x,len=%d",__func__,rb,data,len);
return 0;
}
/*以下操作rb禁止被抢占,否则会导致其他任务获取的读写指针不是实时的,所以这里暂时将抢占优先级抬到0*/
quec_rtos_task_sched_lock();
r_free_size = __kfifo_rb_free_space(rb);
w_size = len < r_free_size ? len : r_free_size;
/* first put the data starting from write_pos to buffer end */
w_free_size = w_size < (rb->size-(rb->wpos&(rb->size-1))) ? w_size : (rb->size-(rb->wpos&(rb->size-1)));
memcpy(rb->data+(rb->wpos&(rb->size-1)), data, w_free_size);
/* then put the rest (if any) at the beginning of the buffer */
memcpy(rb->data, data+w_free_size, w_size-w_free_size);
rb->wpos += w_size;
quec_rtos_task_sched_unlock();
return w_size;
}
判断状态
- 空状态
unsigned int __kfifo_rb_is_empty(quec_ring_buf_t *rb)
{
char ret=0;
ret = (rb->wpos == rb->rpos);
return ret;
}
- 满状态
unsigned int __kfifo_rb_is_full(quec_ring_buf_t *rb)
{
char ret=0;
ret=(rb->size == (rb->wpos-rb->rpos));
return ret;
}
- 剩余空间
unsigned int __kfifo_rb_free_space(quec_ring_buf_t *rb)
{
unsigned int len = 0;
len = rb->size - (rb->wpos - rb->rpos);
return len;
}
- 使用空间
unsigned int __kfifo_rb_data_len(quec_ring_buf_t *rb)
{
unsigned int len = 0;
len = rb->wpos - rb->rpos;
return len;
}
上述是ringbuf源码的实现,代码很精简,可以使用在嵌入式系统的方方面面,希望对大家带来帮助
1354

被折叠的 条评论
为什么被折叠?



