ring buffer实质上是在一块连续的内存上对数据进行写入和读取,只是在写入和读取的时候有些不同。每次读取的时候都要从开辟空间的地址加上一个读取的偏移量读取,相对应的,写入的时候也要从开辟空间的地址加上一个写入的偏移量来写入。重点也就在读取和写入数据上面。下面从代码上面来说一下。

  1. 首先定义一个ring buffer的结构体
typedef struct
{uint8_t *buffer;      //存放实际的数据int32_t read_offset;  //读取地址相对buffer的偏移量int32_t write_offset; //写入地址相对buffer的偏移量int32_t valid_size;   //buffer的有效sizeint32_t total_size;   //buffer的总大小,即init时malloc的size} ring_buffer_t;
  1. 初始化ring buffer
/**1. 初始化ring_buffer2. malloc开辟传入的buff_size大小的空间存放buffer3. read_offset write_offset valid_size均置为0
*/
void ring_buffer_init(ring_buffer_t *ring_buffer, int32_t buff_size)
{ring_buffer->buffer = malloc(buff_size);memset(ring_buffer->buffer, 0, buff_size);ring_buffer->read_offset = 0;ring_buffer->write_offset = 0;ring_buffer->valid_size = 0;ring_buffer->total_size = buff_size;
}
  1. 释放ring buffer
/***释放ring_buffer */
void ring_buffer_deinit(ring_buffer_t *ring_buffer)
{if (ring_buffer->buffer != NULL){free(ring_buffer->buffer);}memset(ring_buffer, 0, sizeof(ring_buffer_t));
}

4.向ring buffer里面写入数据,写入之后需要注意valid_size和write_offset的改变

/*** buffer_to_write:需要写入的数据的地址* size:需要写入的数据的大小
*/
void ring_buffer_write(void *buffer_to_write, int32_t size, ring_buffer_t *ring_buffer)
{int32_t write_offset = ring_buffer->write_offset;int32_t total_size = ring_buffer->total_size;int32_t first_write_size = 0;if (ring_buffer->valid_size + size > total_size) //ring_buffer->buffer未使用的总大小比需要写入的size小{printf("ring buffer is to short to save buff\n");printf("total_size:%d valid_size:%d size:%d\n", ring_buffer->total_size, ring_buffer->valid_size, size);return;}if (size + write_offset <= total_size) //ring_buffer->buffer的后段未写入的空间不小于size{memcpy(ring_buffer->buffer + write_offset, buffer_to_write, size);}else //ring_buffer->buffer的后段未写入的空间小于size,这时候需要先在后面写入一部分,然后返回头部,从前面接着写入{first_write_size = total_size - write_offset;memcpy(ring_buffer->buffer + write_offset, buffer_to_write, first_write_size);memcpy(ring_buffer->buffer, buffer_to_write + first_write_size, size - first_write_size);}ring_buffer->write_offset += size;ring_buffer->write_offset %= total_size;ring_buffer->valid_size += size;
}

附上图帮助理解:

5.从ring buffer里读取数据,写入之后需要注意valid_size和read_offset的改变

void ring_buffer_read(ring_buffer_t *ring_buffer, void *buff, int32_t size)
{int32_t read_offset = ring_buffer->read_offset;int32_t total_size = ring_buffer->total_size;int32_t first_read_size = 0;if (size > ring_buffer->valid_size){printf("valid size < read size\n");printf("valid size:%d read size:%d\n", ring_buffer->valid_size, size);return;}if (total_size - read_offset >= size){memcpy(buff, ring_buffer->buffer + read_offset, size);}else{first_read_size = total_size - read_offset;memcpy(buff, ring_buffer->buffer + read_offset, first_read_size);memcpy(buff + first_read_size, ring_buffer->buffer, size - first_read_size);}ring_buffer->read_offset += size;ring_buffer->read_offset %= total_size;ring_buffer->valid_size -= size;
}

希望本文能帮助到读者,最后附上一个测试:


int main()
{ring_buffer_t ring_buffer;uint8_t buf[8] = "1234abcd";uint8_t buf2[6] = {0};ring_buffer_init(&ring_buffer, RING_BUFFER_SIZE);//RING_BUFFER_SIZE我用宏定义为8ring_buffer_write(buf, sizeof(buf), &ring_buffer); //ring_buffer->buffer="1234abcd"ring_buffer_read(&ring_buffer, buf2, 6); //ring_buffer->buffer="1234abcd" buf2="1234ab"ring_buffer_write(buf + 2, 6, &ring_buffer); //ring_buffer->buffer="34abcdcd"ring_buffer_read(&ring_buffer, buf2, 6); //ring_buffer->buffer="34abcd78" buf2="7834ab"ring_buffer_write("12345678abcd", 12, &ring_buffer);ring_buffer_deinit(&ring_buffer);return 0;
}

ring buffer的C语言实现相关推荐

  1. Ring Buffer (circular Buffer)环形缓冲区简介

    https://blog.csdn.net/langeldep/article/details/8888582 关于环形缓冲区的知识,请看这里 http://en.wikipedia.org/wiki ...

  2. Ring Buffer 的应用

    origin: http://blog.codingnow.com/2012/02/ring_buffer.html 这是一篇命题作文,源于今天在微薄上的一系列讨(好吧,也可以说是吵架).其实方案没有 ...

  3. 环形缓冲区的实现原理(ring buffer)

    消息队列锁调用太频繁的问题算是解决了,另一个让人有些苦恼的大概是这太多的内存分配和释放操作了.频繁的内存分配不但增加了系统开销,更使得内存碎片不断增多,非常不利于我们的服务器长期稳定运行.也许我们可以 ...

  4. SQL Server 环形缓冲区(Ring Buffer) -- 介绍

    SQL Server 环形缓冲区(Ring Buffer) -- 介绍 以下关于Ring Buffer的介绍转载自: http://zh.wikipedia.org/wiki/%E7%92%B0%E5 ...

  5. leetcode 622. Design Circular Queue | 622. 设计循环队列(Ring Buffer)

    题目 https://leetcode.com/problems/design-circular-queue/ 题解 Ring Buffer 的实现,rear 指向新插入的位置,front 指向最旧的 ...

  6. Java 环形缓冲器(Ring Buffer)

    环形缓冲器(Ring Buffer):环形队列,这里使用数组实现,但并未用上环形功能,因为设置了队满直接出队清空队列,如果只读取部分数据,又或者想要覆盖冲写,则可以用上环形功能 package cha ...

  7. SQL Server 环形缓冲区(Ring Buffer) -- 环形缓冲在AlwaysOn的应用

    SQL Server 环形缓冲区(Ring Buffer) -- 环形缓冲在AlwaysOn的应用 可以从SQL Server环形缓冲区得到一些诊断AlwaysOn的信息,或从sys.dm_os_ri ...

  8. 解析Disruptor:写入ring buffer

    原文地址http://mechanitis.blogspot.com/2011/07/dissecting-disruptor-writing-to-ring.html 这是Disruptor end ...

  9. linux+循环buffer,说说循环缓冲区(Ring Buffer)

    关于循环缓冲区(Ring Buffer)的概念,其实来自于Linux内核(Maybe),是为解决某些特殊情况下的竞争问题提供了一种免锁的方法.这种特殊的情况就是当生产者和消费者都只有一个,而在其它情况 ...

最新文章

  1. 如何利用离散Hopfield神经网络进行高校科研能力评价(2)
  2. JPA(二)之CRUD操作
  3. Adobe flash cs5 的Java运行时环境初始化错误 完美解决方法
  4. HTML(二):表格元素
  5. 洛谷 P3803 多项式乘法
  6. db2 springboot 整合_springboot的yml配置文件通过db2的方式整合mysql代码示例
  7. jdbc获取mysql表数据类型_jdbc操作数据库并自动获取字段类型
  8. 210124阶段三信号屏蔽,管道通信
  9. mybaitplus 根据id批量进行修改_批量重命名工具
  10. 前端学习(573):margin无效情形table无效
  11. SpringBoot-探索回顾Spring框架本质
  12. Ubuntu16.04安装MySQL5.7
  13. 微信公众号 语音转文字api_微信重新上线的灰度测试功能:语音上滑转文字发送...
  14. java删除多选项_java – 选项菜单默认灰色边框删除
  15. Android 5.0 Screen pinning 屏幕固定功能
  16. Unity寻路的功能总结
  17. GitHub如何在README.md文件中插入图片
  18. 模块 calendar
  19. Xilinx ISE14.2新手入门
  20. 在sublime text 3中让.vue文件的内容变成彩色

热门文章

  1. 卡塔尔世界杯 A组第一场第一球进球无效判罚越位犯规是没有问题的,大家可以参考一下
  2. 片上变化(on chip variation,OCV)概念学习
  3. (一)人工智能大纲摘要:《人工智能发展白皮书-技术架构篇(2018年9月)》
  4. 20201006 泰克示波器和电脑连接(一)
  5. 泰克示波器MD03012-一款高性能、高可靠性的仪器
  6. undo表空间使用率99%居高不下
  7. python pyquery_python3解析库pyquery
  8. 计算机专业课程评价,计算机专业学生学习的自我评价
  9. 洛谷OJ:P4779 【模板】单源最短路径(标准版)
  10. 计算机常见的内部接口,计算机内部接口大全!