当前位置:网站首页>C语言--环形缓存区
C语言--环形缓存区
2022-08-04 02:28:00 【Coder_貔貅】
环形缓存区工作原理
环形缓冲区是固定大小的缓冲区,工作原理就像内存是连续的且可循环。在生成和使用内存时,不需要将原来的数据全部清理掉,只要调整head/tail指针即可。当添加数据时,head指针前进。当使用数据时,tail指针向前移动。当到达缓冲区的尾部时,指针又回到缓冲区的起始位置。
优势:当有大量数据但不需要全部存储的情况下,计算机在处理数据时会先处理先来的,处理完之后会把数据释放掉,再继续处理下一个。那么已经处理的数据的内存就会被浪费掉。因为后来的数据只能往后排队,如果将剩余的数据都往前移动一次,效率便会大大降低。因此环形队列就出现了。核心是申请一段内存,通过特殊方法让其首尾相连,形成一个闭环的内存地址。这样既可以继续处理源源不断的数据,又不用再去申请新的内存空间暂存新的数据,效率大大提高。
劣势:环形缓冲区最重要的一个特点是写的速度和读的速度匹配性问题,环形缓冲区一般是将数据先写入缓冲区内,然后有个写的指针位置,但是不能超过读的位置,因为数据还未被读取,便写入数据,就会造成数据还未被读取便被新的数据覆盖,造成数据的丢失。读数据同样原理,读的指针不能超过写的位置,这样就会读到之前读过的数据,造成数据的重复。空间如果设置的太大,会造成内存的浪费,有内存一直处于空闲状态,如果空间设置到的太小,可能会造成读的速度快于写的速度,导致读的过程中会有短暂的等待时间,造成效率不是最高。
1、写入数据<缓冲区
2、写入数据>缓冲区
代码:
#include "RingBuffer.h"
static UINT16 validlen; //已使用的数据长度
static UINT8* pHead = NULL; //环形缓冲区首地址
static UINT8* pTail = NULL; //环形缓存区尾地址
static UINT8* pValid = NULL; //已使用缓冲区的首地址
static UINT8* pValidTail = NULL; //已使用缓冲区的尾地址
//malloc申请空间
void initRingbuffer(void)
{
if(pHead == NULL)
{
pHead = (char*) malloc(BUFFER_SIZE);
}
pValid = pValidTail = pHead;
pTail = pHead + BUFFER_SIZE;
validlen = 0;
}
//释放环形缓冲区
void releaseRingbuffer(void)
{
if(pHead != NULL)
free(pHead);
pHead = NULL;
}
/*************************************************************/
/******功能:初始化指定的环形缓冲区 *****/
/******param:@buffer:定义静态缓冲区数组的首地址
param:@size:该缓冲区的大小 ******/
/************************************************************/
void InitRingBuffer(UINT8* buffer, UINT16 size)
{
if(pHead == NULL)
{
pHead = buffer;
}
pValid = pValidTail = pHead;
pTail = pHead + size;
validlen = 0;
}
/***********************************************************/
/******功能:向缓冲区写入数据 *****/
/******param:@buffer 写入的数据指针
@len 写入的数据长度 ******/
/******return:-1 写入的数据长度过大 -2:缓冲区未初始化 *****/
/***********************************************************/
int writeRingbuffer(UINT8* buffer, UINT32 len)
{
UINT16 len1, len2, movelen;
if(len > BUFFER_SIZE)
{
return -1;
}
if(pHead == NULL)
{
return -2;
}
assert(buffer);
//将要写入的数据copy到pVaildTaill处
if(pValidTail+len > pTail)
{
len1 = pTail - pValidTail; //放到尾部
len2 = len - len1; //尾部放不下的位置,从头开始放
memcpy(pValidTail, buffer, len1);
memcpy(pHead, buffer + len1, len2);
pValidTail = pHead + len2; //新的有效数据
}else
{
memcpy(pValidTail, buffer, len);
pValidTail += len; //新的有效数据区结尾
}
//重新计算已使用区的起始位置
if(validlen + len > BUFFER_SIZE)
{
movelen = validlen + len - BUFFER_SIZE;
if(pValid + movelen > pTail) //需要分成两段
{
len1 = pTail - pValid;
len2 = movelen - len1;
pValid = pHead + len2;
}else
{
pValid += movelen;
}
validlen = BUFFER_SIZE;
}else
{
validlen += len;
}
return 0;
}
/*************************************************************/
/******功能:从缓冲区读取指定长度的数据 *****/
/******param:@buffer 接收读取数据的指针
@length 读取的数据长度 ******/
/******return:-1 缓冲区未初始化 >0:读取的有效数据大小 *****/
/*************************************************************/
int readRingbuffer(UINT8* buffer, UINT32 len)
{
UINT16 len1, len2;
if(pHead == NULL)
{
return -1;
}
assert(buffer);
if(len > validlen)
{
len = validlen;
}
if(validlen == 0)
{
return 0;
}
if(pValid + len > pTail) //需要分成两段copy
{
len1 = pTail - pValid;
len2 = len - len1;
memcpy(buffer, pValid, len1); //第一段
memcpy(buffer + len1, pHead, len2); //第二段 ,绕到整个存储区的开头
pValid = pHead + len2; //更新已使用缓冲区的起始
}else
{
memcpy(buffer, pValid, len);
pValid += len; //更新已使用缓冲区的起始
}
validlen -= len; //更新已使用缓冲区的长度
return len;
}
/*************************************************************/
/******功能:获取已使用的缓冲区数据长度 *****/
/******param:void ******/
/******return:已使用缓冲区的数据长度 *****/
/************************************************************/
UINT32 getRingbufferValidLen(void)
{
return validlen;
}
边栏推荐
- 各位大佬好,麻烦问一下flink cdc oracle写入doris的时候,发现cpu异常,一下下跑
- Parquet encoding
- Web APIs BOM - operating browser: swiper plug-in
- 香港服务器有哪些常用的型号
- Hey, I had another fight with HR in the small group!
- Example 040: Reverse List
- flinkcdc 消费 mysql binlog 没有 sqltype=delete 的数据是什么原
- 实例040:逆序列表
- Simple sorting (summer vacation daily question 14)
- Download install and create/run project for HBuilderX
猜你喜欢
随机推荐
Continuing to invest in product research and development, Dingdong Maicai wins in supply chain investment
内网穿透-应用
工程制图平面投影练习
Flink原理流程图简单记录
浏览器存储
Hey, I had another fight with HR in the small group!
深度学习(三)分类 理论部分
实例036:算素数
瑞能微计量芯片RN2026的实用程序
QNX Hypervisor 2.2用户手册]10.2 vdev 8259
22/8/3(板子)树状dp板子+中国剩余定理+求组合数3,4+容斥原理
html select tag assignment database query result
持续投入商品研发,叮咚买菜赢在了供应链投入上
priority_queue元素为指针时,重载运算符失效
Continuing to invest in product research and development, Dingdong Maicai wins in supply chain investment
单片机C语言->的用法,和意思
Utilities of Ruineng Micrometer Chip RN2026
Kubernetes:(九)coredns(浪不动了)
idea中diagram使用
实例039:有序列表插入元素