ring buffer的C语言实现
ring buffer实质上是在一块连续的内存上对数据进行写入和读取,只是在写入和读取的时候有些不同。每次读取的时候都要从开辟空间的地址加上一个读取的偏移量读取,相对应的,写入的时候也要从开辟空间的地址加上一个写入的偏移量来写入。重点也就在读取和写入数据上面。下面从代码上面来说一下。
- 首先定义一个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;
- 初始化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;
}
- 释放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语言实现相关推荐
- Ring Buffer (circular Buffer)环形缓冲区简介
https://blog.csdn.net/langeldep/article/details/8888582 关于环形缓冲区的知识,请看这里 http://en.wikipedia.org/wiki ...
- Ring Buffer 的应用
origin: http://blog.codingnow.com/2012/02/ring_buffer.html 这是一篇命题作文,源于今天在微薄上的一系列讨(好吧,也可以说是吵架).其实方案没有 ...
- 环形缓冲区的实现原理(ring buffer)
消息队列锁调用太频繁的问题算是解决了,另一个让人有些苦恼的大概是这太多的内存分配和释放操作了.频繁的内存分配不但增加了系统开销,更使得内存碎片不断增多,非常不利于我们的服务器长期稳定运行.也许我们可以 ...
- SQL Server 环形缓冲区(Ring Buffer) -- 介绍
SQL Server 环形缓冲区(Ring Buffer) -- 介绍 以下关于Ring Buffer的介绍转载自: http://zh.wikipedia.org/wiki/%E7%92%B0%E5 ...
- leetcode 622. Design Circular Queue | 622. 设计循环队列(Ring Buffer)
题目 https://leetcode.com/problems/design-circular-queue/ 题解 Ring Buffer 的实现,rear 指向新插入的位置,front 指向最旧的 ...
- Java 环形缓冲器(Ring Buffer)
环形缓冲器(Ring Buffer):环形队列,这里使用数组实现,但并未用上环形功能,因为设置了队满直接出队清空队列,如果只读取部分数据,又或者想要覆盖冲写,则可以用上环形功能 package cha ...
- SQL Server 环形缓冲区(Ring Buffer) -- 环形缓冲在AlwaysOn的应用
SQL Server 环形缓冲区(Ring Buffer) -- 环形缓冲在AlwaysOn的应用 可以从SQL Server环形缓冲区得到一些诊断AlwaysOn的信息,或从sys.dm_os_ri ...
- 解析Disruptor:写入ring buffer
原文地址http://mechanitis.blogspot.com/2011/07/dissecting-disruptor-writing-to-ring.html 这是Disruptor end ...
- linux+循环buffer,说说循环缓冲区(Ring Buffer)
关于循环缓冲区(Ring Buffer)的概念,其实来自于Linux内核(Maybe),是为解决某些特殊情况下的竞争问题提供了一种免锁的方法.这种特殊的情况就是当生产者和消费者都只有一个,而在其它情况 ...
最新文章
- 如何利用离散Hopfield神经网络进行高校科研能力评价(2)
- JPA(二)之CRUD操作
- Adobe flash cs5 的Java运行时环境初始化错误 完美解决方法
- HTML(二):表格元素
- 洛谷 P3803 多项式乘法
- db2 springboot 整合_springboot的yml配置文件通过db2的方式整合mysql代码示例
- jdbc获取mysql表数据类型_jdbc操作数据库并自动获取字段类型
- 210124阶段三信号屏蔽,管道通信
- mybaitplus 根据id批量进行修改_批量重命名工具
- 前端学习(573):margin无效情形table无效
- SpringBoot-探索回顾Spring框架本质
- Ubuntu16.04安装MySQL5.7
- 微信公众号 语音转文字api_微信重新上线的灰度测试功能:语音上滑转文字发送...
- java删除多选项_java – 选项菜单默认灰色边框删除
- Android 5.0 Screen pinning 屏幕固定功能
- Unity寻路的功能总结
- GitHub如何在README.md文件中插入图片
- 模块 calendar
- Xilinx ISE14.2新手入门
- 在sublime text 3中让.vue文件的内容变成彩色
热门文章
- 卡塔尔世界杯 A组第一场第一球进球无效判罚越位犯规是没有问题的,大家可以参考一下
- 片上变化(on chip variation,OCV)概念学习
- (一)人工智能大纲摘要:《人工智能发展白皮书-技术架构篇(2018年9月)》
- 20201006 泰克示波器和电脑连接(一)
- 泰克示波器MD03012-一款高性能、高可靠性的仪器
- undo表空间使用率99%居高不下
- python pyquery_python3解析库pyquery
- 计算机专业课程评价,计算机专业学生学习的自我评价
- 洛谷OJ:P4779 【模板】单源最短路径(标准版)
- 计算机常见的内部接口,计算机内部接口大全!