Ring Buffer介绍
Ring Buffer的高级用法(类似内核KFIFO)
环形缓冲区(ring buffer),环形队列(ring queue) 多用于2个线程之间传递数据,是标准的先入先出(FIFO)模型。一般来说,对于多线程共享数据,需要使用mutex来同步,这样共享数据才不至于发生不可预测的修改/读取,然而,mutex的使用也带来了额外的系统开销,ring buffer/queue 的引入,就是为了有效地解决这个问题,因其特殊的结构及算法,可以用于2个线程中共享数据的同步,而且必须遵循1个线程push in,另一线程pull out的原则。
线程 A 媒介 线程 B
data in --> ring buffer/queue --> data out
参考代码
代码参考Linux内核Kfifo
.
数据结构
数据结构中定义的缓存区大小一定要是2的n,当然也可以用动态分配来分配缓存区的大小,但是使用该高级用法一定要遵循分配的缓存区大小是2的n次方;
#define MIN(a, b) (((a) < (b)) ? (a) : (b)) /* 取a和b中最小值 */#define RING_BUFFER_SIZE 4096 //大小一定要为2的n次方才能使用该高级用法 typedef struct {char buffer[RING_BUFFER_SIZE]; /* 缓冲区 ,大小一定要为2的n次方才能使用该高级用法 */unsigned int size; /* 大小 注意要用unsigned类型*/unsigned int in; /* 入口位置 注意要用unsigned类型*/unsigned int out; /* 出口位置 注意要用unsigned类型*/
} RingBuffer_t;
先说明数据结构定义时为什么要要求指针和大小的数据类型一定要为unsigned,因为在
本高级用法中,没有用size的大小限制指针的大小的,入指针与出指针的大小均可以达到对于数据大小的最大值,
而我们知道无符号类型的数据,大小超过最大值时,会出现溢出,导致数值又会从零开始变化,
比如unsigned char, 254 + = 1,就是255 ,而255在计算机中的二进制存储为11111111,所以255+1,
入队列
unsigned int RingBufferPut(RingBuffer_t *ring_buf_p, void *buffer, hd_u32_t size)
{unsigned int len = 0;if(ring_buf_p == NULL || buffer == NULL) {return -1;}/*得到实际写入的数据长度*/size = MIN(size, ring_buf_p->size - ring_buf_p->in + ring_buf_p->out);/*min(空闲空间大小,从real_in开始到缓冲区结尾的空间) -------------*//* first put the data starting from fifo->in to buffer end */len = MIN(size, ring_buf_p->size - (ring_buf_p->in & (ring_buf_p->size - 1)));memcpy(ring_buf_p->buffer + (ring_buf_p->in & (ring_buf_p->size - 1)), buffer, len);/* then put the rest (if any) at the beginning of the buffer */if (size - len > 0) {memcpy(ring_buf_p->buffer, (char *)buffer + len, size - len);}ring_buf_p->in += size;return size;
}
出队列
unsigned int RingBufferGet(RingBuffer_t *ring_buf_p, void *buffer, hd_u32_t size)
{unsigned int len = 0;if(ring_buf_p == NULL || buffer == NULL) {return -1;}size = MIN(size, ring_buf_p->in - ring_buf_p->out);/* first get the data from fifo->out until the end of the buffer */len = MIN(size, ring_buf_p->size - (ring_buf_p->out & (ring_buf_p->size - 1)));memcpy(buffer, ring_buf_p->buffer + (ring_buf_p->out & (ring_buf_p->size - 1)), len);/* then get the rest (if any) from the beginning of the buffer */if (size - len > 0) {memcpy((char *)buffer + len, ring_buf_p->buffer, size - len);}ring_buf_p->out += size;return size;
}
获取队列中可读数据的大小
unsigned int RingBufferLen(const RingBuffer_t *ring_buf_p)
{return (ring_buf_p->in - ring_buf_p->out);
}
清空循环队列
void RingBufferClear(RingBuffer_t *ring_buf_p)
{ring_buf_p->in = 0;ring_buf_p->out = 0;
}
struct _RingQ
{
SI32 r_cursor;
SI32 w_cursor;
SI32 length;
void* data[0];
};
#ifndef _RING_BUF_H_
#define _RING_BUF_H_/*环形缓冲区管理器*/
typedef struct
{unsigned char *buf; /*环形缓冲区 */unsigned int size; /*环形缓冲区 */unsigned int front; /*头指针 */unsigned int rear; /*尾指针 */
}ring_buf_t;/*-------------------------外部接口声明----------------------------*/int ring_buf_create(ring_buf_t *r,unsigned char *buf,unsigned int size);void ring_buf_clr(ring_buf_t *r);unsigned int ring_buf_len(ring_buf_t *r);unsigned int ring_buf_put(ring_buf_t *r,unsigned char *buf,unsigned int len);unsigned int ring_buf_get(ring_buf_t *r,unsigned char *buf,unsigned int len);#endif/******************************************************************************** 文件名称: ringbuffer.c* 摘 要:环形缓冲区 * 参 考: linux/kfifo * 当前版本: 1.0* 作 者: w* 完成日期: 2016-05-30* ******************************************************************************/#include "ringbuffer.h"
#include <string.h>
#include <stddef.h>
#include <assert.h>#define min(a,b) ( (a) < (b) )? (a):(b) /*******************************************************************************函数名 :ring_buf_init*函数功能 :构造一个空环形缓冲区*输入参数 :r 环形缓冲区控制块*返回值 :非0表示成功 *****************************************************************************/
int ring_buf_create(ring_buf_t *r,unsigned char *buf,unsigned int len)
{r->buf = buf;r->size = len;r->front = r->rear = 0;return buf == NULL;
}
/***********************************************************************函数名 :ring_buf_clr*函数功能 :清空环形缓冲区 *输入参数 :r - 待清空的环形缓冲区*返回值 :None *********************************************************************/
void ring_buf_clr(ring_buf_t *r)
{r->front = r->rear = 0;
}/***********************************************************************函数名 :ring_buf_len*函数功能 :计算环形缓冲区容量 (字节为单位)*输入参数 :r.环形缓冲区控制块*返回值 :环形缓冲区中有效字节数 *********************************************************************/
unsigned int ring_buf_len(ring_buf_t *r)
{return r->rear - r->front;
}/***********************************************************************函数名 :ring_buf_put*函数功能 :将指定长度的数据放到环形缓冲区中 *输入参数 :buf - 数据缓冲区* len - 缓冲区长度 *返回值 :实际放到中的数据 *********************************************************************/
unsigned int ring_buf_put(ring_buf_t *r,unsigned char *buf,unsigned int len)
{unsigned int i;unsigned int space; space = r->size + r->front - r->rear;len = min(len , space); /*得到实际写入的数据长度*//*min(空闲空间大小,从real_in开始到缓冲区结尾的空间) -------------*/i = min(len, r->size - r->rear % r->size); /** 当len > l时,拷贝buffer中剩余的内容*而剩余的大小为len - l */ memcpy(r->buf + r->rear % r->size, buf, i); memcpy(r->buf, buf + i, len - i); r->rear += len; return len;}/***********************************************************************函数名 :rueueGet*函数功能 :从环形缓冲区中读取指定长度的数据 *输入参数 :len - 读取长度 *输出参数 :buf - 输出数据缓冲区*返回值 :实际读取长度 *********************************************************************/
unsigned int ring_buf_get(ring_buf_t *r,unsigned char *buf,unsigned int len)
{unsigned int i;unsigned int space; space = r->rear - r->front; len = min(len , space); i = min(len, r->size - r->front % r->size ); memcpy(buf, r->buf + r->front % r->size, i); memcpy(buf + i, r->buf, len - i); r->front += len; return len;
}
Ring Buffer介绍相关推荐
- SQL Server 环形缓冲区(Ring Buffer) -- 介绍
SQL Server 环形缓冲区(Ring Buffer) -- 介绍 以下关于Ring Buffer的介绍转载自: http://zh.wikipedia.org/wiki/%E7%92%B0%E5 ...
- Ring Buffer (circular Buffer)环形缓冲区简介
https://blog.csdn.net/langeldep/article/details/8888582 关于环形缓冲区的知识,请看这里 http://en.wikipedia.org/wiki ...
- Linux ftrace 1.1、ring buffer
1.简介 ringbuffer是trace框架的一个基础,所有的trace原始数据都是通过ringbuffer记录的.ringbuffer的作用主要有几个: 1.存储在内存中,速度非常快,对系统性能的 ...
- 优秀的内存规划方法——环形缓冲区(ring buffer)
目录 什么是环形缓冲区 使用环形buffer的好处 环形buffer的使用场景 进程间通信 网络IO 区分缓冲区是满或者是空 计数 保持一个存储单元为空 镜像指示位 buffer满了之后的操作 实时流 ...
- 环形缓冲区的实现原理(ring buffer)
消息队列锁调用太频繁的问题算是解决了,另一个让人有些苦恼的大概是这太多的内存分配和释放操作了.频繁的内存分配不但增加了系统开销,更使得内存碎片不断增多,非常不利于我们的服务器长期稳定运行.也许我们可以 ...
- ringbuffer java例子_使用Ring Buffer构建高性能的文件写入程序
最近常收到SOD框架的朋友报告的SOD的SQL日志功能报错:文件句柄丢失.经过分析得知,这些朋友使用SOD框架开发了访问量比较大的系统,由于忘记关闭SQL日志功能所以出现了很高频率的日志写入操作,从而 ...
- 使用 Ring Buffer 完成数据传递
使用 Ring Buffer 完成数据传递 概述 在前述章节中,我们依次介绍了 Queue.StreamBuffer.MessageBuffer.上述三者尽管提供了一定的数据缓存能力,但没有提供管理数 ...
- leetcode 622. Design Circular Queue | 622. 设计循环队列(Ring Buffer)
题目 https://leetcode.com/problems/design-circular-queue/ 题解 Ring Buffer 的实现,rear 指向新插入的位置,front 指向最旧的 ...
- protocol buffer介绍(protobuf)
protocol buffer介绍(protobuf) @(HADOOP)[hadoop, 大数据] 一.理论概述 0.参考资料 入门资料:https://developers.google.com/ ...
- Java 环形缓冲器(Ring Buffer)
环形缓冲器(Ring Buffer):环形队列,这里使用数组实现,但并未用上环形功能,因为设置了队满直接出队清空队列,如果只读取部分数据,又或者想要覆盖冲写,则可以用上环形功能 package cha ...
最新文章
- java中添加数组元素
- 7.Mahout菩萨
- 微信支付开发(2) 微信支付账号体系
- git 出现 fatal: refusing to merge unrelated histories 错误
- DSP学习-- UTC转UNIX时间戳
- ubuntu21.04 simplescreenrecorder录屏没有声音解决办法
- linux看电视系统,教你如何在Linux操作系统下观看电视节目
- mysql 修复错误连接_mysql 无法连接问题的定位和修复过程分享
- 物资申请php,php学生捐赠物品管理系统
- node.js学习笔记5——核心模块1
- 长安链chainmaker 修改共识方法
- 计算机局域网硬件维护与网络安全的分析
- 蜻蜓和蝉c语言,趣味数学:蜻蜓、蜘蛛、蝉它们的翅膀和腿
- java mybatis优点_mybatis优缺点是什么?有哪些优点和缺点?
- 联想计算机CDROM启动,光驱启动,联想电脑光驱启动
- STL和泛型编程_学习笔记01
- Win7安全模式启动卡在Classpnp.sys
- 分区 与 bios 笔记本 tips
- C语言-广度优先遍历
- ubuntu server 14.04 编译安装xen4.4.2配置vtpm(一)——xen4.4.2源码编译安装