循环buffer“一写多读“

news2024/11/18 7:44:33

1.往期回顾

  1. 一个简单实用的循环buffer,用于缓冲数据!测试500M数据,耗时1.3秒。

  2. C语言版本的循环buffer比C++版本的速度更快!测试500M数据0.5秒,达9.25Gbps左右!

  3. C 语言免拷贝版本循环 buffer 比拷贝版本快了近 10 倍!

之前分享过一些循环buffer缓冲区的实现,有C++版本的、C语言版本的、C语言免拷贝版本的,本质上都是基于环形缓冲区思想实现的"一写一读"循环buffer,今天给大家分享一个"一写多读"版本的循环buffer。

2. 简介

”一写多读“循环buffer即一个写者往循环buffer缓冲区写入数据,多个读者从循环buffer缓冲区读取数据,通过管理各种读写指针的位置进行数据保护。通过这种机制实现一份数据共享给不同模块使用且互不干扰,隔离模块,降低耦合

”一写多读“循环buffer的示意图如下所示,本例中有3个读指针,1个写指针,所有指针顺时针方向移动。红色区域是写指针写入数据,暂无读者读取数据;绿色区域是部分读者未读完数据的区域;黄色区域是所有读者都读完数据的区域。

图1 "一写多读"循环buffer 示意图

图1 "一写多读"循环buffer 示意图

3. 设计思想

要想实现读写指针流动且访问数据不冲突,即把握两点:对照下图

  1. 写指针不能追上超过最后一个读指针,即本例中的读指针1,此时对于写指针来讲,可写入数据的空间为黄色部分。

  2. 所有读者不能追上超过写指针。本例中读指针3此时可读取数据的区域为红色部分;读指针2此时可读取数据区域是蓝色+红色区域;读指针3此时可读取数据区域是绿色+蓝色+红色区域。

图2 "一写多读循环buffer 指针标识图

图2 "一写多读循环buffer 指针标识图

4. 设计实现

循环缓冲区本质是一块连续的内存空间,通过管理读写指针位置实现数据共享,如下图所示。当指针到达右边边界即buffer结束地址,通过取余的方式讲指针回环到左边对应位置,实现循环流动。

图3 "一写多读"循环buffer 内存布局

图3 "一写多读"循环buffer 内存布局

结构体设计及函数设计如下,包含写指针,读者数组,因为读者数目可配置。add函数指针实现添加读者,read实现读取数据,write实现向缓冲区写入数据。

typedef struct m_ringbuffer
{
    struct readpos_t *arr_pos[MAX_READ_NUM];/* 读者信息数组    */  
    volatile int w_pos;          /* 写入数据指针位置 */
    int          read_cnt;       /* 读者数量       */
    int rb_overflow_cnt;         /* 记录缓冲区溢出的次数     */
    int rb_size, rb_size_mask;   /* 缓冲区空间大小  */
    uint8_t*      rb_buffer;     /* 缓存数据空间    */
    int (*add)(void* pthis);     /* 向循环buffer添加一个读者 */
    int (*write)(void* pthis, const uint8_t* buffer, int len); /* 写数据函数 */
    int (*read)(void* pthis, int readid, uint8_t **buffer, int len); /* 读数据函数 */
}m_ringbuffer_t;

/**
 * @brief 从循环buffer空间读取数据
 * @param pthis 循环buffer句柄
 * @param readid 读者的id,区分读者
 * @param buffer 要的数据指针的地址
 * @param len 要读取数据的长度
 * @return -1:参数错误 -2:可读空间不够 len:读取的数据长度
*/
static int mrb_read(void* pthis, int readid, uint8_t **buffer, int len);

/**
 * @brief 向循环buffer空间写入数据
 * @param pthis 循环buffer句柄
 * @param buffer 要写入的数据
 * @param len 要写入数据的长度
 * @return -1:参数错误 -2:可写空间不够 0:写入成功
*/
int mrb_write(void* pthis, const uint8_t* buffer, int len);

/**
 * @brief 向循环buffer添加读者
 * @param pthis 循环buffer句柄
 * @return -1:添加失败  id:读者ID
*/
static int mrb_add(void* pthis);

5. 使用示例

int ret, len, data_len, id;
uint8_t *buf;

 //创建缓冲区
 m_ringbuffer_t* rb = create_muti_ringbuffer(50*1024);
 //添加读者
 id = rb->add(rb);
 //往循环buffer中写数据
 ret = rb->write(rb, buf, data_len); 
 //从缓冲区读取数据
 rb->read(rb, read_id, &buf, data_len);

完整工程代码见:https://github.com/young-1-code/data_structure.git取代码的小伙伴请帮忙点一个star吧~感谢~

编译平台:Linux系统 编译工具:GCC 编译:输入make进行编译,工程测试是读写文件进行的,所以需要给一个数据源路径,可参考往期循环buffer测试,见开篇链接。

图4 代码位置

图4 代码位置

6.总结

至此我们实现了”一写一读“、”一写多读“循环buffer,每一种实现版本都有它合适的应用场景,需要根据具体需求选择。实现不同的数据结构不是重点,本系列循环buffer有多种不同变体,本质上都是根据循环缓冲区设计实现的,所以重点是一种理解设计思想,通过迁移变换,设计不同数据结构满足不同需求场景。 欢迎大家一起交流学习,帮忙点赞、在看、转发吧~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1710713.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

熵值法(熵权法)

熵值法(Entropy Method)是一种多属性决策分析方法,主要用于权重确定、排序和评价。它在风险评估、资源配置、环境管理等领域得到广泛应用。熵值法的核心思想是基于信息熵的概念,利用信息熵来度量各属性对决策的贡献程度&#xff0…

农产品产品防伪防窜货+二维码防伪+溯源系统源码全平台一物一码数字化防伪防窜货和溯源查询系统

农产品产品防伪防防窜货二维码防伪溯源系统源码全平台一物一码数字化防伪防窜货和溯源查询系统 产品防伪防防窜货二维码防伪溯源系统源码,该系统采用最简单易用的phpMySQL进行搭建,拥有完善的网站前后台,通过对每件产品生产线上的单品、二级…

BIGO前端CICD平台

本文首发于:https://github.com/bigo-frontend/blog/ 欢迎关注、转载。 我是谁 BIGO前端CICD平台,是一个服务于前端团队的全研发周期管理平台,已经是我们团队日常都要使用的工具了。 该平台实现了一键创建项目、发布编排、新建迭代、checkl…

【微服务】部署mysql集群,主从复制,读写分离

两台服务器做如下操作 1.安装mysqldocker pull mysql:5.72.启动以及数据挂载 mkdir /root/mysql/data /root/mysql/log /root/mysql/conf touch my.conf //mysql的配置文件docker run --name mysql \ -e MYSQL_ROOT_PASSWORD123456 \ -v /root/mysql/data:/var/lib/mysql \ -v…

如何创建一个vue项目?详细教程,如何创建第一个vue项目?

已经安装node.js在自己找的到的地方新建一个文件夹用于存放项目,记住文件夹的存放路径,以我为例,我的文件夹路径为D:\tydic 打开cmd命令窗口,进入刚刚的新建文件夹 切换硬盘: D: 进入文件夹:cd tydic 使…

基于ViutualBox+Ubuntu(Linux)的开发环境搭建

实际在选择虚拟机的时候纠结了要用virualbox还是vmware,初步比较结果: 1.virualbox能够使用vmware的硬盘格式,因此可以自由选择。 2.都能够实现主机和宿主机之间的文件夹共享。 3.virualbox是自由软件,vmware是商业软件。 在功能上…

STM32 入门教程(江科大教材)#笔记2

3-4按键控制LED /** LED.c**/ #include "stm32f10x.h" // Device headervoid LED_Init(void) {/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_I…

go 微服务框架kratos使用中间件的方法

一、中间件的概念 在go语言中,中间件是一种用于处理http请求的开发模式,允许开发人员在请求到达处理程序之前或之后执行特定的操作,如日志记录、身份验证、错误处理等。 中间件通常是一个函数,它接收一个 http.Handler 作为参数…

解读makefile中$(patsubst pattern,replacement,text)

在 Makefile 中,$(patsubst pattern,replacement,text) 是一个用于模式替换的函数,它可以将文本中符合指定模式的部分替换为指定的字符串。这个函数通常用于对文件名或路径进行模式匹配和替换,非常适合在 Makefile 中进行文件名的转换操作。 …

队列的特性及代码实现(C语言)

目录 队列的定义 队列的实现分析 代码实现 Queue.h Queue.c 队列的定义 队列是只允许在一端进行插入操作,而在另一段进行删除操作的线性表。 首先,让我们来看一看生活中的队列,当我们去银行办理业务的时候,我们进入银行的时候…

CANDela studio使用小tips

打开软件的时候注意先选择英文,因为双击CDD/CDDT文件默认打开的是德文,所以最正确的打开方式是先打开CANDela studio,再导入CDD,不仅可以避免用德文打开,还能避免vector软件的bug。 不同的版本有不同的权限。 admin有…

【一竞技DOTA2】RAMZES666替补参加裂变联赛

1、根据主办方文件,RAMZES666将继续作为Tundra战队替补参加裂变联赛。该比赛为欧洲线上赛,于5月27日-30日举行,总奖金8万美元。 除此之外,Nigma战队在上个月宣布四号位Matthew离队后,也选择启用老队员GH参赛。而在本月初让ah fu转回教练、携替补Thiolicor出战PGL瓦拉几亚的Secr…

《Navi日语社》App支持日语翻译、日文OCR文字识别提取、文字转语音和语音识别功能!

随着中日交流日益频繁,学习日语和日语翻译的需求也愈发强烈。为满足广大用户的需求,《Navi日语社》App应运而生,成为您日语学习与翻译的不二之选! 日语翻译,准确无误。凭借先进的机器翻译技术,我们的App可…

Qt串口异步通信案例(从机线程)

文章目录 串口线程类初始化串口类打开串口并发送数据析构函数 窗口设置窗口函数实现 串口线程类 SlaveThread(从机线程) 目的:等待并响应来自主机的请求,然后发送预设的响应数据。 关键行为:线程启动后,通过…

打造爆款活动:确定目标受众与吸引策略的实战指南

身为一名文案策划经理,我深知在活动策划的海洋中,确定目标受众并设计出能触动他们心弦的策略是何等重要。 通过以下步骤,你可以更准确地确定目标受众,并制定出有效的吸引策略,确保活动的成功: 明确活动目…

C++线程任务队列模型

功能描述 实现一个任务队列,用于任务的执行 任务队列 任务队列可以添加、删除任务,实现对任务的管理添加任务后,任务队列可以开始执行任务队列执行任务方式为串行执行 任务 任务执行需要持续一段10s内随机的时间,执行过程通过…

npm install node-sass 安装失败的解决方案:利用国内镜像加速安装

在开发前端项目时,使用Sass作为CSS预处理器是很多开发者的选择。然而,在通过npm安装其Node.js绑定库node-sass时,一些开发者可能会遇到安装失败的问题,尤其是网络原因导致的下载缓慢或中断。本文将指导你如何通过更换为国内镜像源…

联邦和反射器实验

拓扑图 一.实验要求 1.AS1存在两个环回,一个地址为192.168.1.0/24,该地址不能在任何协议中宣告 AS3存在两个环回,一个地址为192.168.2.0/24,该地址不能在任何协议中宣告 AS1还有一个环回地址为10.1.1.0/24&#xff…

【kubernetes】关于k8s集群的污点、容忍、驱逐以及k8s集群故障排查思路

目录 一、污点(Taint) 1.1污点介绍 1.2污点的组成格式 1.3当前 taint effect 支持如下三个选项: 1.4污点的增删改查 1.4.1验证污点的作用——NoExecute 1.4.2验证污点的作用——NoSchedule 1.4.3 验证污点的作用——PreferNoSchedule 1.5污点的配置与管理…

Python散点图矩阵代码模版

本文分享Python seaborn实现散点图矩阵代码模版,节选自👉嫌Matplotlib繁琐?试试Seaborn! 散点图矩阵(scatterplot matrix)展示原始数据中所有变量两两之间关系,可以规避单一统计指标的偏差&…