环形缓冲区

  1. 环形缓冲区的特性
    1、先进新出
    2、当缓冲区被使用完,且又有新的数据需要存储时,丢掉历史最久的数据,保存最新数据
    现实中的存储介质都是线性的,因此我们需要做一下处理,才能在功能上实现环形缓冲区

    算法说明:
    1、pHead和pTail分别是连续存储介质的首地址和尾地址
    2、pTail - pHead 的值是环形缓冲区的总长度
    3、pValid 是使用区域的起始指针,取数据时的起点,当取数据时pValid要发生偏移
    4、pValidTail 是使用区域的的结尾指针,存数据时的起点,当存数据时,pValidTail要发生偏移
    5、现有长度为addLen字节要存入,当pValidTail + addLen > pTail 时(超出了缓冲区,这时就要绕到开头pHead)
    int len1 = pTail - pValidTail;
    int len2 = addLen - len1;
    pValidTail = pHead + len2;//新的使用区的尾指针
    6、判断总长度是否变更,即是否有数据覆盖pValid所指向的区域,如果有,要偏移pValid
  • 下面是已验证的代码
    ringBuffer.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "ringBuffer.h"
#define BUFFER_SIZE  16   //缓冲区的长度,可以修改static u32 validLen;//已使用的数据长度
static u8* pHead = NULL;//环形存储区的首地址
static u8* pTail = NULL;//环形存储区的结尾地址
static u8* pValid = NULL;//已使用的缓冲区的首地址
static u8* pValidTail = NULL;//已使用的缓冲区的尾地址/** 初始化环形缓冲区* 环形缓冲区这里可以是malloc申请的内存,也可以是Flash存储介质* */
void initRingbuffer(void)
{if(pHead == NULL){pHead = (u8*) malloc(BUFFER_SIZE);}pValid = pValidTail = pHead;pTail = pHead + BUFFER_SIZE;validLen = 0;
}/** function:向缓冲区中写入数据* param:@buffer 写入的数据指针*         @addLen 写入的数据长度* return:-1:写入长度过大*          -2:缓冲区没有初始化* */
int wirteRingbuffer(u8* buffer,u32 addLen)
{if(addLen > BUFFER_SIZE) return -2;if(pHead==NULL) return -1;assert(buffer);//将要存入的数据copy到pValidTail处if(pValidTail + addLen > pTail)//需要分成两段copy{int len1 = pTail - pValidTail;int len2 = addLen - len1;memcpy( pValidTail, buffer, len1);memcpy( pHead, buffer + len1, len2);pValidTail = pHead + len2;//新的有效数据区结尾指针}else{memcpy( pValidTail, buffer, addLen);pValidTail += addLen;//新的有效数据区结尾指针}//需重新计算已使用区的起始位置if(validLen + addLen > BUFFER_SIZE){int moveLen = validLen + addLen - BUFFER_SIZE;//有效指针将要移动的长度if(pValid + moveLen > pTail)//需要分成两段计算{int len1 = pTail - pValid;int len2 = moveLen - len1;pValid = pHead + len2;}else{pValid = pValid + moveLen;}validLen = BUFFER_SIZE;}else{validLen += addLen;}return 0;
}/** function:从缓冲区内取出数据* param   :@buffer:接受读取数据的buffer*           @len:将要读取的数据的长度* return  :-1:没有初始化*            >0:实际读取的长度* */
int readRingbuffer(u8* buffer,u32 len)
{if(pHead==NULL) return -1;assert(buffer);if(validLen ==0) return 0;if( len > validLen) len = validLen;if(pValid + len > pTail)//需要分成两段copy{int len1 = pTail - pValid;int len2 = len - len1;memcpy( buffer, pValid, len1);//第一段memcpy( buffer+len1, pHead, len2);//第二段,绕到整个存储区的开头pValid = pHead + len2;//更新已使用缓冲区的起始}else{memcpy( buffer, pValid, len);pValid = pValid +len;//更新已使用缓冲区的起始}validLen -= len;//更新已使用缓冲区的长度return len;
}/** function:获取已使用缓冲区的长度* return  :已使用的buffer长度* */
u32 getRingbufferValidLen(void)
{return validLen;
}/** function:释放环形缓冲区* */
void releaseRingbuffer(void)
{if(pHead!=NULL) free(pHead);pHead = NULL;
}

ringBuffer.h

#ifndef RINGBUFFER_H_
#define RINGBUFFER_H_
typedef unsigned char u8;
typedef unsigned int u32;void initRingbuffer(void);
int wirteRingbuffer(u8* buffer,u32 len);
int readRingbuffer(u8* buffer,u32 len);
u32 getRingbufferValidLen(void);
void releaseRingbuffer(void);#endif /* RINGBUFFER_H_ */

测试 main 函数

#include <stdio.h>
#include <stdlib.h>
#include "ringBuffer.h"
// 主函数
int main()
{char c;int readLen;u8 readBuffer[10];//setvbuf(stdout,NULL,_IONBF,0); //pinrtf、putchar不能立马输出,打开此注释initRingbuffer();printf("Please enter a line [blank line to terminate]> ");do{c=getchar();putchar(c);switch(c){case 'Q':goto exit;break;case 'R':readLen = readRingbuffer(readBuffer,10);printf("readRingbuffer len:%d\n",readLen);if(readLen > 0){printf("readRingbuffer:");for(int i=0;i<readLen;i++){printf("%c ",(char)readBuffer[i]);}printf("\n");}break;default :if(c!='\n') wirteRingbuffer((u8*)&c,1);break;}}while (1);exit:releaseRingbuffer();printf("exit.\n");return 0;
}

单片机开发

**注意:请尊重原创者的辛劳,转载请注明


环形缓冲区C语言实现相关推荐

  1. 音视频环形缓冲区C语言实现

    目录 一.什么是环形缓冲区 二.为什么使用环形缓冲区 三.代码实现 一.什么是环形缓冲区 环形缓冲区(也称为循环缓冲区)是固定大小的缓冲区,工作原理就像内存是连续的且可循环的一样.在生成和使用内存时, ...

  2. C语言构建环形缓冲区

    它逻辑上是一个首尾相连的FIFO结构,具体实现上采用简单的线性数组.通过额外的辅助标志(head.tail)能很快知道队列的使用情况(是满还是为空).正因为其简单高效的原因,甚至在硬件都实现了环形队列 ...

  3. 环形缓冲区实现(C语言)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 要求 一.环形缓冲区 二.环形缓冲区实现(C语言) 1. ringBuf.h 2. ringBufInit.c 3. rin ...

  4. c语言数组怎么环形阵列,C语言 用于大阵列的无复制线程安全环形缓冲区

    对于大数组(10 ^ 7个元素)上的信号处理,我使用与环形缓冲区连接的不同线程.遗憾的是,只需要太多时间将数据复制到缓冲区和从缓冲区复制数据.当前实现基于boost :: lockfree :: sp ...

  5. C语言实现环形缓冲区

    文章目录 前言 一.什么是环形缓冲区? 二.为什么要使用环形缓冲区及环形缓冲区实用场景 三.环形缓冲区原理及代码的编写 原理 代码编写 总结 前言 本篇文章将为大家介绍一下什么是环形缓冲区,在很多场合 ...

  6. c语言数组实现环形缓冲区,[嵌入式开发模块]环形缓冲区/循环队列 C语言实现

    忙着毕设,很久没有写文章了,终于答辩完了,得了个校优秀毕业设计.毕设做的是个智能接口模块,用一周时间入门了,MC9S12XEP100的开发,又用一周时间入门了uC/OS-II嵌入式操作系统,在做毕设的 ...

  7. 架构设计:生产者/消费者模式 第6页:环形缓冲区的实现

    2019独角兽企业重金招聘Python工程师标准>>> ◇判断"空"和"满" 上述的操作并不复杂,不过有一个小小的麻烦:空环和满环的时候,R和 ...

  8. Ring Buffer (circular Buffer)环形缓冲区简介

    https://blog.csdn.net/langeldep/article/details/8888582 关于环形缓冲区的知识,请看这里 http://en.wikipedia.org/wiki ...

  9. java环形buff_环形缓冲区.ringbuff(C#和java)

    环形缓冲, 本质就是队列fifo,先进先出的特殊版本,环形队列,是用空间得到了顺序存储的快索引的优点,又避免了删除,移动数据的缺点.并且还享受了单生产/单消费,2线程的无锁线程优势.十分完美. 1.面 ...

最新文章

  1. 硬件:串口的基础知识笔记
  2. go 服务器 源码,LollipopGo开源游戏服务器框架--global服务器源码
  3. JQuery控制只能输入带二位小数的数字
  4. 机器学习笔记【一】- 线性回归(末):统计学推导以及局部加权线性回归算法实例
  5. vxworks7.0SD卡驱动流程及文件系统格式化
  6. 五年级上册用计算机探索规律思维导图,五年级上册数学第一单元思维导图 包括小数乘整数小数乘小数积的...
  7. iOS应用内购常见问题及注意事项
  8. 参加南京mooc活动有感
  9. 坤宝德万达打造命运共同体万达茂天樾之夜.时光发声全国巡回演唱会南宁站圆满结束
  10. Sonatype Nexus3 搭建私有仓库
  11. 数据库软件设计(8684)
  12. 股权转让项目:沈阳派尔化学有限公司55%股权转让
  13. Blast中文手册(2)
  14. 教资笔记(综合素质篇)
  15. vsCode安装使用教程和插件安装
  16. 在面试时,向面试官介绍项目的基本要点
  17. 华钜同创:亚马逊滞销产品快速清仓的方法!
  18. 克莱因瓶在现实中为什么不存在
  19. Easy File Sharing Server7.2漏洞复现
  20. java 调用虚拟打印机_通过虚拟打印机获取其他软件的数据,实现数据传输

热门文章

  1. Linux那些事儿之我是U盘(51)光荣属于苹果,属于诺基亚,属于摩托罗拉,属于索尼爱立信
  2. Redis主从复制、哨兵、集群
  3. 函数的四种特性——有界性 单调性 奇偶性 周期性
  4. php获取手机ime,关于IME
  5. [论文总结] 深度学习在农业领域应用论文笔记11
  6. JSON Hero 好用的json工具
  7. C语言 字符串比较不用strcmp函数
  8. 拆析promise.then的.then返回值
  9. mac误删相片怎么恢复?
  10. 新浪微博数据库资源调度设计:万级实例精细化管理