什么是循环缓冲区的用途?

32

循环缓冲区的一些用途是什么?

使用循环缓冲区的好处是什么?

它是否可以替代双向链表?

7个回答

42

我曾将它用作限制大小的内存日志。例如,应用程序会在处理用户请求时写入日志条目。每当出现(可能会破坏处理过程的)异常时,当前在内存中的日志记录将被倾倒。

循环缓冲区的好处是,你不需要无限量的内存,因为旧条目会自动被覆盖。 "挑战" 在于,你需要找到适合你用例的合适大小。在上面的例子中,如果最重要的关于异常的日志记录已经被覆盖,那就非常不幸了。

一些系统/应用程序有工具让你按需提取缓冲区的当前内容,而不仅仅是在自动提取(如果有的话)时。

我认为ETW和CLR的stress log在许多其他系统的内核或高性能跟踪/日志记录中都是这样实现的。

实际上,使用此类缓冲区进行内存跟踪/日志记录的概念相当常见(不只是这种用途-当然不是),因为它比将记录写入你可能永远不会感兴趣的文件/数据库要快得多。相关说明,它节省了硬盘空间。


16
“我已使用过它”比“你可以使用它”更恰当,应该加1赞同。 - ryeguy

15
循环缓冲区适用于嵌入式系统中的串行数据流。微控制器通常具有UART以处理传入的串行字节,这些字节需要按顺序存储并稍后处理(字节经常以比能够处理的速度更快的速率进入)。
缓冲区有效地将时间关键响应要求(当字节在微秒级别上进入时)与整个消息的非时间关键响应(例如在毫秒级别上显示接收到的消息)分开处理,例如:
1)在接收字节时,UART可以生成一个中断,软件通过快速接收并将其推送到缓冲区来做出响应。
2)然后,后台软件例程可以定期检查缓冲区是否有内容,并根据需要将其清空。
由于循环缓冲区大小可以在预编译时定义,因此其大小是受限制的。这有助于提高空间效率,并应消除内存损坏,但会以数据开始丢失之前可以接收多少字节为代价。

9
循环缓冲区是一种有效地维护有序值/项的滑动/移动列表的机制。一个例子可能是维护最近N个项的滑动平均值。假设您想追踪计算某个值的最后100次操作的平均成本。为此,您需要删除最旧的成本并添加最新的成本。
如果没有循环缓冲区,一种代价高昂的方法(C风格)是拥有一个100个元素的数组。每次计算新成本时,您可以将99个元素memmove向下并在最后位置放置新元素。这显然是代价高昂的。使用循环缓冲区的想法,您只需跟踪缓冲区的“末尾”(位置0-99)。它将标记最旧(或最新...无论您选择哪个)成本项的位置。读取旧值(用于更新运行平均值)后,您将其替换为最新值并增加缓冲区位置(如果它在99,则将其设置回0...因此是循环部分)。
与双向链表进行比较并没有太多意义。循环缓冲区当然可以使用双向链表(甚至是单向链表)实现。但是将它们进行比较有点像比较苹果和橙子。

7
我知道这是作弊,但维基百科确实有非常好的解释。

http://en.wikipedia.org/wiki/Circular_buffer

循环缓冲区、循环缓存或环形缓冲区是一种数据结构,它使用一个单一的固定大小缓冲区,就好像它是端对端连接的一样。这种结构非常适合于缓冲数据流。
可能会使用覆盖式循环缓冲区的示例是多媒体应用。如果将该缓冲区用作生产者-消费者问题中的有界缓冲区,那么如果消费者(例如声卡)暂时无法跟上,则生产者(例如音频生成器)可能希望覆盖旧数据。另一个例子是数字波导综合方法,它使用循环缓冲区来有效地模拟弦乐或管乐器的声音。
关于比较双向链表,我想这确实取决于您使用列表的目的... 实现循环缓冲区似乎更加复杂,请参考维基页面;该页面解释了实现、注意事项等,并显示了示例代码。
谢谢,尼尔

1
我的第一个SO问题的答案使用了循环缓冲区来生成音频。http://stackoverflow.com/questions/664594/how-to-generate-a-guitar-note - Scott Chamberlain

0

我将其用作实现轮询调度的简单方法。基本上,我有一堆不同的对象,可以产生一个值,消费者可以处理该值。我把所有的生产者都放在一个环中,依次询问每个生产者。


0

我在多线程代码中使用了环形缓冲区。基本上,如果所有插槽都已满,则生产者必须等待。消费者仅处理“满”插槽中的项目。

这是一个我发起的帖子。它提供了一些关于实现的好建议。

.NET 多线程变量访问


0

我认为最重要的答案是:“当你想按创建顺序顺序读取生成的数据,并且不关心除了最后接收到的第n个数据之外的旧数据时,需要考虑内存敏感任务。”


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接