假设我们有一个环形缓冲区,其大小(RING_BUFFER_SIZE)为8字节。初始情况下,缓冲区是空的:
索引: 0 1 2 3 4 5 6 7
数据: [ ][ ][ ][ ][ ][ ][ ][ ]
头: ^
尾: ^
在这个例子中,头(head)和尾(tail)索引都是0,表示下一个数据应写入数组的第0位,下一个读取也应该是第0位。
当我们写入3个字节的数据(例如A,B,C)后,环形缓冲区看起来将是:
索引: 0 1 2 3 4 5 6 7
数据: ['A']['B']['C'][ ][ ][ ][ ][ ]
头: ^
尾: ^
现在,头索引指向位置3,表示下一个字节将被写入此处。尾索引仍然指向位置0,表示下一个字节将从此处读取。
假设我们继续写入5个字节的数据(D, E, F, G, H),环形缓冲区将变为:
索引: 0 1 2 3 4 5 6 7
数据: ['A']['B']['C']['D']['E']['F']['G']['H']
头: ^
尾: ^
此时头和尾的索引都回到了0。头索引回到了0是因为('H'后,head = (7 + 1) % 8),就等于0。如果我们现在尝试写入更多数据,RingBuffer_Write将返回false,因为缓冲区已满。
如果我们接着读取4个字节,每次读取都会让尾索引增加,然后环形缓冲区会是这样的:
索引: 0 1 2 3 4 5 6 7
数据: ['A']['B']['C']['D']['E']['F']['G']['H']
头: ^
尾: ^
在这个状态下,尾索引指向4,表示下一个字节将从这里读取。由于缓冲区不再是满的,我们现在可以再次写入数据。
如果我们现在写入三个字节的数据(I, J, K),环形缓冲区的状态将更新如下:
索引: 0 1 2 3 4 5 6 7
数据: ['I']['J']['K']['D']['E']['F']['G']['H']
头: ^
尾: ^
头索引移动到位置3,并覆盖了那里旧的数据。因为我们已经读取了那些数据,所以这是安全的。这个行为使得环形缓冲区非常适合处理连续的数据流,而不需要大量的内存分配和复制操作。
以上来之GPT4.