zl程序教程

您现在的位置是:首页 >  其它

当前栏目

环形缓冲区

缓冲区 环形
2023-09-27 14:27:56 时间

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

1、环形缓冲区的实现原理

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

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

2、实例:环形缓冲区的实现

环形缓冲区是数据通信程序中使用最为广泛的数据结构之一,下面的代码,实现了一个环形缓冲区:

ExpandedBlockStart.gif/*ringbuf .c*/
None.gif
None.gif#i nclude stdio. h
None.gif
None.gif    #i nclude ctype. h
None.gif
None.gif#define NMAX 8
None.gif
ExpandedBlockStart.gifint iput = 0; /* 环形缓冲区的当前放人位置 */
None.gif
ExpandedBlockStart.gifint iget = 0; /* 缓冲区的当前取出位置 */
None.gif
ExpandedBlockStart.gifint n = 0; /* 环形缓冲区中的元素总数量 */
None.gif
None.gifdouble buffer[NMAX]; 
None.gif
ExpandedBlockStart.gif/*  环形缓冲区的地址编号计算函数,,如果到达唤醒缓冲区的尾部,将绕回到头部。
InBlock.gif
InBlock.gif环形缓冲区的有效地址编号为:0到(NMAX-1)
InBlock.gif
ExpandedBlockEnd.gif*/
None.gif
None.gifint addring (int i)
None.gif
ExpandedBlockStart.gif{
InBlock.gif
InBlock.gif        return (i+1) == NMAX ? 0 : i+1;
InBlock.gif
ExpandedBlockEnd.gif}
None.gif
ExpandedBlockStart.gif/* 从环形缓冲区中取一个元素 */
None.gif
ExpandedBlockStart.gifdouble get{void}
None.gif
ExpandedBlockStart.gif{
InBlock.gif
InBlock.gifcnt pos;
InBlock.gif
ExpandedSubBlockStart.gifif (n 0){
InBlock.gif
InBlock.gif           Pos = iget;
InBlock.gif
InBlock.gif           iget = addring(iget);
InBlock.gif
InBlock.gif           n--;
InBlock.gif
InBlock.gif           return buffer[pos];
InBlock.gif
ExpandedSubBlockEnd.gif}
InBlock.gif
ExpandedSubBlockStart.gifelse {
InBlock.gif
InBlock.gifprintf(“Buffer is empty\n”);
InBlock.gif
InBlock.gifreturn 0.0;
InBlock.gif
ExpandedSubBlockEnd.gif}
InBlock.gif
ExpandedSubBlockStart.gif/* 向环形缓冲区中放人一个元素*/
InBlock.gif
InBlock.gifvoid put(double z)
InBlock.gif
ExpandedSubBlockStart.gif{
InBlock.gif
ExpandedSubBlockStart.gifif (n NMAX){
InBlock.gif
InBlock.gif           buffer[iput]=z;
InBlock.gif
InBlock.gif           iput = addring(iput);
InBlock.gif
InBlock.gif           n++;
InBlock.gif
ExpandedSubBlockEnd.gif}
InBlock.gif
InBlock.gifelse
InBlock.gif
InBlock.gifprintf(“Buffer is full\n”);
InBlock.gif
ExpandedSubBlockEnd.gif}
InBlock.gif
InBlock.gif 
InBlock.gif
ExpandedSubBlockStart.gifint main{void)
InBlock.gif
ExpandedSubBlockStart.gif{
InBlock.gif
InBlock.gifchat opera[5];
InBlock.gif
InBlock.gifdouble z;
InBlock.gif
ExpandedSubBlockStart.gifdo {
InBlock.gif
InBlock.gifprintf(“Please input p|g|e?”);
InBlock.gif
InBlock.gifscanf(“%s”,  opera);
InBlock.gif
ExpandedSubBlockStart.gif               switch(tolower(opera[0])){
InBlock.gif
ExpandedSubBlockStart.gif               case ‘p’: /* put */
InBlock.gif
InBlock.gif                  printf(“Please input a float number?”);
InBlock.gif
InBlock.gif                  scanf(“%lf”, 
InBlock.gif
InBlock.gif                  put(z);
InBlock.gif
InBlock.gif                  break;
InBlock.gif
ExpandedSubBlockStart.gifcase ‘g’: /* get */
InBlock.gif
InBlock.gif                  z = get();
InBlock.gif
InBlock.gifprintf(“%8.2f from Buffer\n”, z);
InBlock.gif
InBlock.gifbreak;
InBlock.gif
InBlock.gifcase ‘e’:
InBlock.gif
InBlock.gif                  printf(“End\n”);
InBlock.gif
InBlock.gif                  break;
InBlock.gif
InBlock.gifdefault:
InBlock.gif
InBlock.gif                  printf(“%s - Operation command error! \n”, opera);
InBlock.gif
ExpandedSubBlockStart.gif}/* end switch */
InBlock.gif
ExpandedSubBlockEnd.gif}while(opera[0] != ’e’);
InBlock.gif
InBlock.gif    return 0;
InBlock.gif
ExpandedSubBlockEnd.gif}
InBlock.gif
环形缓冲区 环形缓冲区 是一段 先进先出 的循环缓冲区,有一定的大小,我们可以把它抽象理解为一块环形的内存。 我们使用环形缓冲区主要有两个原因; (1)当我们要存储大量数据时,我们的计算机只能处理先写入的数据,处理完毕释放数据后,后面的数据需要前移一位,大量的数据会频繁分配释放内存,从而导致很大的开销。使用环形缓冲区 可以减少内存分配继而减少系统的开销。 (2)如果我们频繁快速的持续向计算机输入数据,计算机可能执行某个进程不能及时的执行输入的数据,导致数据丢失。这时,我们可以将要输入的数据放入环形缓冲区内,计算机就不会造成数据丢失。
一.空间分配器 # 一.空间分配器 ### 分配内存: * 当容器需要空间来存放元素时,需要空间配置器(也就是分配器)分配内存,当分配的内存大于128个字节时,调用第一级配置器,调用malloc为其分配内存,当分配内存小于128个字节时,调用第二级配置器,检查对应的free-list上是否有可用区块,如果有的话,直接拿来用,如果没有的话调用rfill。
linux内存分配方法总结【转】 转自:http://www.bkjia.com/Linuxjc/443717.html 内存映射结构:1.32位地址线寻址4G的内存空间,其中0-3G为用户程序所独有,3G-4G为内核占有。2.struct page:整个物理内存在初始化时,每个4kb页面生成一个对应的struct page结构,这个page结构就独一无二的代表这个物理内存页面,并存放在mem_map全局数组中。
数据块Block是Oracle存储数据信息的最小单位。注意,这里说的是Oracle环境下的最小单位。Oracle也就是通过数据块来屏蔽不同操作系统存储结构的差异。