dyli之环形缓冲区初探

简介: 1、环形缓冲区ringbuffer原理   在通信程序中,经常使用环形缓冲区作为数据结构来存放通信中发送和接收的数据。环形缓冲区是一个先进先出的循环缓冲区,可以向通信程序提供对缓冲区的互斥访问。

1、环形缓冲区ringbuffer原理

 

在通信程序中,经常使用环形缓冲区作为数据结构来存放通信中发送和接收的数据。环形缓冲区是一个先进先出的循环缓冲区,可以向通信程序提供对缓冲区的互斥访问。

 

环形缓冲区通常有一个读指针和一个写指针。读指针指向环形缓冲区中可读的数据,写指针指向环形缓冲区中可写的缓冲区。通过移动读指针和写指针就可以实现缓冲区的数据读取和写人。在通常情况下,环形缓冲区的读用户仅仅会影响读指针,而写用户仅仅会影响写指针。如果仅仅有一个读用户和一个写用户,那么不需要添加 互斥保护机制就可以保证数据的正确性。如果有多个读写用户访问环形缓冲区,那么必须添加互斥保护机制来确保多个用户互斥访问环形缓冲区。

 

1、图2和图3是一个环形缓冲区的运行示意图。图1是环形缓冲区的初始状态,可以看到读指针和写指针都指向第一个缓冲区处;图2是向环形缓冲区中添加了一个数据后的情况,可以看到写指针已经移动到数据块2的位置,而读指针没有移动;图3是环形缓冲区进行了读取和添加后的状态,可以看到环形缓冲区中已经添加了两个数据,已经读取了一个数据。

 

img_01981edc351af4574b6fea86d88b2d5f.jpg

   
 
 
2、dyli修改版程序
 
  1. /********************ringbuf .c*************************/

  2. #include stdio.h>
  3. #include ctype.h>
  4. #define MAXNUM 3

  5. int currentInputPlace=0;//环形缓冲区的当前放入位置,初始为0

  6. int currentOutputPlace=0;//环形缓冲区的当前取出位置,初始为0

  7. int n=0;    //环形缓冲区中的当前可用元素的总数量,初始为0

  8. double buffer[MAXNUM];


  9. /***************************************************************************************************
  10.     环形缓冲区的地址编号计算函数,如果到达唤醒缓冲区的尾部 ,将绕回头部。
  11.     环形缓冲区的有效地址编号为:0-->(MAXNUM-1)
  12. **************************************/
  13. int addMemberToRing(int i)
  14. {
  15.     return (i+1) == MAXNUM?0:i+1;
  16.                                     /*是否到环形的尾部,是:返回0;否:返回一个缓冲区的编号*/
  17. }


  18. /**************************************************************************************************
  19.     从环形缓冲区中取一个元素
  20. *************************************/
  21. double get(void)
  22. {
  23.     int pos;
  24.     if(n>0)
  25.     {
  26.         pos=currentOutputPlace;//从第0个位置开始

  27.         currentOutputPlace=addMemberToRing(currentOutputPlace);//

  28.         n--;    //当前可用元素少一个

  29.         return buffer[pos];
  30.     }
  31.     else
  32.     {
  33.         printf("dyli find Buffer is empty \n");
  34.         return 0.0;
  35.     }
  36. }


  37. /**************************************************************************************************
  38.     向环形缓冲区放入一个元素    
  39. *************************************/
  40. void put(double z)
  41. {
  42.     if(nMAXNUM)
  43.     {
  44.         buffer[currentInputPlace]=z;//将元素填入

  45.         currentInputPlace=addMemberToRing(currentInputPlace);//当前输入位置下移一个

  46.         n++;//当前可用元素多一个

  47.     }
  48.     else//达到8个则提醒缓冲区已满

  49.     {
  50.         printf("dyli find Buffer is full \n");
  51.     }
  52. }


  53. /**************************************************************************************************
  54.     main()    
  55. *************************************/
  56. int main(void)
  57. {
  58.     char opera[5];
  59.     double z;
  60.     do{
  61.         printf("dyli ask you to input p|g|e?");
  62.         scanf("%s",&opera);
  63.         switch(tolower(opera[0]))//函数将tolower()可以将字符串转换成小写字母

  64.         {
  65.             case 'p':/* put */
  66.                     printf("Please input a float number:");
  67.                     scanf("%lf",&z);
  68.                     put(z);
  69.                     break;
  70.             case 'g':/* get */
  71.                     z=get();
  72.                     printf("%8.2f from buffer \n",z);
  73.                     break;
  74.             case 'e':
  75.                     printf("dyli say :The end.\n");
  76.                     break;
  77.             default :
  78.                     printf("%s --yout operator command error !\n",opera);                
  79.         }/*end of switch*/
  80.     }while(opera[0]!='e');
  81.     return 0;
  82. }

 

运行结果:

[root@localhost ringbuf]# ./ringbuf

dyli ask you to input p|g|e?p

Please input a float number:1

dyli ask you to input p|g|e?p

Please input a float number:2

dyli ask you to input p|g|e?p

Please input a float number:3

dyli ask you to input p|g|e?p

Please input a float number:4

dyli find Buffer is full

dyli ask you to input p|g|e?g

    1.00 from buffer

dyli ask you to input p|g|e?g

    2.00 from buffer

dyli ask you to input p|g|e?g

    3.00 from buffer

dyli ask you to input p|g|e?g

dyli find Buffer is empty

    0.00 from buffer

dyli ask you to input p|g|e?e

dyli say :The end.

[root@localhost ringbuf]#

 
相关文章
|
2月前
在使用realloc给已分配的堆区空间追加空间时需要注意的点
使用 `realloc` 函数为已分配的堆区空间追加空间时,需要注意以下几点:1. 原有指针可能失效;2. 分配失败会返回 NULL,原有内存不变;3. 新空间可能被重新分配到其他位置。确保检查返回值并妥善处理。
|
6月前
|
程序员 编译器 C++
C++内存分区模型(代码区、全局区、栈区、堆区)
C++内存分区模型(代码区、全局区、栈区、堆区)
|
7月前
|
程序员 编译器 C++
内存分区模型(代码区、全局区、栈区、堆区)
内存分区模型(代码区、全局区、栈区、堆区)
|
7月前
|
编译器 C语言
动态内存的管理(内存储存的god)
动态内存的管理(内存储存的god)
41 0
|
7月前
mmap匿名映射区
mmap匿名映射区
|
7月前
|
定位技术
环形缓冲区RingBuff
环形缓冲区RingBuff
如何设置交换区swap空间
如何设置交换区swap空间
123 0
|
存储 程序员 编译器
C语言内存分区(堆,栈,全局/静态存储区,自由存储区,代码区)与可执行程序的三段-(Text段,Date段,Bss段)
C语言内存分区(堆,栈,全局/静态存储区,自由存储区,代码区)与可执行程序的三段-(Text段,Date段,Bss段)
264 0
|
存储
环形缓冲区
环形缓冲区 是一段 先进先出 的循环缓冲区,有一定的大小,我们可以把它抽象理解为一块环形的内存。 我们使用环形缓冲区主要有两个原因; (1)当我们要存储大量数据时,我们的计算机只能处理先写入的数据,处理完毕释放数据后,后面的数据需要前移一位,大量的数据会频繁分配释放内存,从而导致很大的开销。使用环形缓冲区 可以减少内存分配继而减少系统的开销。 (2)如果我们频繁快速的持续向计算机输入数据,计算机可能执行某个进程不能及时的执行输入的数据,导致数据丢失。这时,我们可以将要输入的数据放入环形缓冲区内,计算机就不会造成数据丢失。
116 0
|
存储 安全 C语言
C语言实现环形缓冲区
C语言实现环形缓冲区
206 0