当前位置:网站首页>C language -- ring buffer
C language -- ring buffer
2022-08-04 02:35:00 【Coder_Pixiu】
How the ring buffer works
Ring buffers are fixed-size buffers,Works like memory is contiguous and loopable.在生成和使用内存时,There is no need to clear all the original data,只要调整head/tail指针即可.当添加数据时,head指针前进.当使用数据时,tail指针向前移动.当到达缓冲区的尾部时,指针又回到缓冲区的起始位置.

优势:When there is a lot of data but you don't need to store it all,Computers process data first,After processing, the data will be released,Proceed to the next one.Then the memory for the processed data will be wasted.因为后来的数据只能往后排队,If the remaining data are moved forward once,Efficiency will be greatly reduced.Hence the circular queue.The core is to apply for a piece of memory,Connect them end to end by a special method,形成一个闭环的内存地址.这样既可以继续处理源源不断的数据,There is no need to apply for new memory space to temporarily store new data,效率大大提高.
劣势:One of the most important features of the ring buffer is the matching between the speed of writing and the speed of reading,环形缓冲区一般是将数据先写入缓冲区内,然后有个写的指针位置,但是不能超过读的位置,Because the data has not been read yet,write data,This will cause the data to be overwritten by new data before it has been read,造成数据的丢失.Reading data is the same principle,The read pointer cannot exceed the write location,这样就会读到之前读过的数据,造成数据的重复.空间如果设置的太大,会造成内存的浪费,有内存一直处于空闲状态,If the space is set too small,可能会造成读的速度快于写的速度,导致读的过程中会有短暂的等待时间,造成效率不是最高.
1、写入数据<缓冲区

2、写入数据>缓冲区

代码:
#include "RingBuffer.h"
static UINT16 validlen; //已使用的数据长度
static UINT8* pHead = NULL; //The first address of the ring buffer
static UINT8* pTail = NULL; //Ring buffer end address
static UINT8* pValid = NULL; //The first address of the used buffer
static UINT8* pValidTail = NULL; //The end address of the used buffer
//malloc申请空间
void initRingbuffer(void)
{
if(pHead == NULL)
{
pHead = (char*) malloc(BUFFER_SIZE);
}
pValid = pValidTail = pHead;
pTail = pHead + BUFFER_SIZE;
validlen = 0;
}
//Free the ring buffer
void releaseRingbuffer(void)
{
if(pHead != NULL)
free(pHead);
pHead = NULL;
}
/*************************************************************/
/******功能:Initializes the specified ring buffer *****/
/******param:@buffer:Defines the first address of the static buffer array
param:@size:The size of this buffer ******/
/************************************************************/
void InitRingBuffer(UINT8* buffer, UINT16 size)
{
if(pHead == NULL)
{
pHead = buffer;
}
pValid = pValidTail = pHead;
pTail = pHead + size;
validlen = 0;
}
/***********************************************************/
/******功能:向缓冲区写入数据 *****/
/******param:@buffer 写入的数据指针
@len 写入的数据长度 ******/
/******return:-1 The length of the data written is too large -2:The buffer is not initialized *****/
/***********************************************************/
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; //The position where the rear can't be put down,从头开始放
memcpy(pValidTail, buffer, len1);
memcpy(pHead, buffer + len1, len2);
pValidTail = pHead + len2; //New valid data
}else
{
memcpy(pValidTail, buffer, len);
pValidTail += len; //End of new valid data area
}
//Recalculate the starting position of the used area
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;
}
/*************************************************************/
/******功能:Reads the specified length of data from the buffer *****/
/******param:@buffer Pointer to receive read data
@length 读取的数据长度 ******/
/******return:-1 The buffer is not initialized >0:Valid data size read *****/
/*************************************************************/
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); //第二段 ,Wrap around to the beginning of the entire store
pValid = pHead + len2; //Update the start of the used buffer
}else
{
memcpy(buffer, pValid, len);
pValid += len; //Update the start of the used buffer
}
validlen -= len; //Update the length of the used buffer
return len;
}
/*************************************************************/
/******功能:Get the used buffer data length *****/
/******param:void ******/
/******return:The data length of the used buffer *****/
/************************************************************/
UINT32 getRingbufferValidLen(void)
{
return validlen;
}
边栏推荐
- Continuing to invest in product research and development, Dingdong Maicai wins in supply chain investment
- 一文看懂推荐系统:召回04:离散特征处理,one-hot编码和embedding特征嵌入
- Use of lombok annotation @RequiredArgsConstructor
- 实例039:有序列表插入元素
- Flutter3.0线程——四步教你如何全方位了解(事件队列)
- Example: 036 is a prime number
- Web APIs BOM - operating browser: swiper plug-in
- [Playwright Test Tutorial] 5 minutes to get started
- 2022.8.3-----leetcode.899
- Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行(含系列目录)。
猜你喜欢
随机推荐
Snake game bug analysis and function expansion
单片机C语言->的用法,和意思
贪吃蛇游戏Bug解析及功能扩展
实例037:排序
云开发校园微社区微信小程序源码/二手交易/兼职交友微信小程序开源源码
董明珠直播时冷脸离场,员工频犯低级错误,自家产品没人能弄明白
多线程间的通信方式你知道几种?
ssh服务详解
[Playwright Test Tutorial] 5 minutes to get started
Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行(含系列目录)。
【云原生】DevOps(六):Jenkins流水线
MallBook 助力SKT思珂特教育集团,立足变化,拥抱敏捷交易
在更一般意义上验算移位距离和假设
Good bosses, please ask the flink CDC oracle to Doris, found that the CPU is unusual, a run down
web端动效 lottie-web 使用
Promise solves blocking synchronization and turns asynchronous into synchronous
Simple sorting (summer vacation daily question 14)
There are too many systems, how to realize multi-account interworking?
C程序编译和预定义详解
5. Scrapy middleware & distributed crawler








