环形缓冲区

目录

环形缓冲区

1.什么是环形缓冲区

2.如何使用环形缓冲区

3.环形buffer的应用场景


1.什么是环形缓冲区

环形缓冲区是一个先进先出(FIFO)的闭环存储空间,用于表示一个固定尺寸、头尾相连的缓冲区的数据结构,适合缓存数据流,在内存用尽后,剩余未存的数据从这段内存的起始位置开始存放,适用于多线程、多进程和网络IO的数据处理,一个读一个写,反复使用内存,降低空间复杂度

2.如何使用环形缓冲区

使用环形缓冲区时,定义了两个指针,一个写指针,一个读指针。读指针指向环形缓冲区可读数据的第一个数据地址,写指针指向环形环形缓冲区可写数据的第一个数据地址。如下图,10个数据大小的Buffer,写入了5个数据,其读、写指针指向位置。

  • 写操作(需要先判断环形缓冲区是否已写满)
//判断环形缓冲区是否满
//写位置的下一位为读位置
static int isInputBufferFull(void)
{
    return (g_iRead == ((g_iWrite + 1) % BUFFER_LEN));
}

//向环形缓冲区中写数据
static void PutInputEventToBuffer(PInputEvent ptInputEvent)
{
	if (!isInputBufferFull())
	{
		g_atInputEvents[g_iWrite] = *ptInputEvent;
		g_iWrite = (g_iWrite + 1) % BUFFER_LEN;
	}
}


若已写满,最直接简单的方式就是直接覆盖原先已写的数据;


  • 读操作(需要先判断环形缓冲区是否为空)
//判断环形缓冲区是否空
//读位置等于写位置
static int isInputBufferEmpty(void)
{
    return (g_iRead == g_iWrite);
}

//从环形缓冲区中读数据
static int GetInputEventFromBuffer(PInputEvent ptInputEvent)
{
	if (!isInputBufferEmpty())
	{
		*ptInputEvent = g_atInputEvents[g_iRead];
		g_iRead = (g_iRead + 1) % BUFFER_LEN;
		return 1;
	}
	else
	{
		return 0;
	}
}

若为空,则无法读取数据

这种取余计算读写位置的方法会使得实际可存数据量与缓冲区容量不一致

特别地,当有多个任务需要读写环形缓冲区时,必须添加互斥保护机制,确保每个任务均正确访问环形缓冲区

3.环形buffer的应用场景

  • 多进程通信

用于共享内存,只需要一定长度的共享内存就可以循环传输大量数据进行通信;

  • 多线程通信

用于并发的输入输出,应用于同时处理多种输入方式,如触摸屏输入和网络输入等;

  • 网络IO

使用socket,原因是共享内存安全性较低。 方案是,为每一个链接都准备一个环形缓冲区,用于临时存放接收到的数据,以应付半包及粘包的情况。解包解密后,将数据包再复制到逻辑线程消息队列中。