循环缓冲区有哪些用途?
使用循环缓冲区有什么好处?
它是双链表的替代品吗?
我已将它用于大小受限的内存日志。例如,应用程序会在处理用户请求时写入日志条目。每当发生异常(这将破坏处理)时,当前在内存中的日志记录将与它一起被转储。
循环缓冲区的好处是,您不需要无限量的内存,因为旧条目会自动被覆盖。“挑战”是,您需要为您的用例找到合适的尺寸。在上面的示例中,如果包含有关异常的最重要信息的日志记录已经被覆盖,那将是非常不幸的。
一些系统/应用程序有工具可以让您按需提取缓冲区的当前内容,而不仅仅是在自动提取时(如果有的话)。
我相信ETW和 CLRs压力日志以及许多其他系统的内核或高性能跟踪/日志记录都是以这种方式实现的。
使用此类缓冲区进行内存跟踪/记录的概念实际上很常见(并不是说这是唯一的用途——当然不是),因为它比将记录写入文件/数据库要快得多,而你可能永远不会感兴趣,除非发生错误。并且在相关说明中,它可以节省硬盘空间。
循环缓冲区适用于嵌入式系统中的串行数据流。微控制器通常有一个 UART 来处理传入的串行字节,这些需要按顺序存储并稍后处理(字节通常以比处理速度更快的速度传入)。
缓冲区有效地将所需的时间关键响应(当字节进来时,以微秒为单位)拆分为对整个消息的非时间关键响应(例如显示进来的消息,以毫秒为单位),例如:
1) 在接收到一个字节后,UART 可以产生一个中断,软件通过快速获取接收到的字节并将其推到缓冲区的末尾来响应该中断。
2) 然后后台软件例程可以定期检查缓冲区中是否还有任何内容,并根据需要清空。
由于可以在编译前定义循环缓冲区大小,因此大小受到限制。这有助于提高空间效率,并且应该在数据开始丢失之前权衡可以接收多少字节来消除内存损坏。
循环缓冲区是一种很好的机制,可以有效地以有序的方式维护值/项的滑动/移动列表。一个例子可能是保持最后 N 个项目的滑动平均值。假设您要跟踪计算某个值的最后 100 次操作的平均成本。为此,您需要删除最旧的成本并添加最新的成本。
如果没有循环缓冲区,执行此操作(C 风格)的代价高昂的机制是拥有一个包含 100 个元素的数组。每次计算新成本时,您可以将 99 个元素向下移动并将新元素放在最后一个位置。这显然代价高昂。使用循环缓冲区的想法,您只需跟踪缓冲区的“结束”(位置 0-99)。它将标记最旧(或最新……无论您选择哪个)成本项目的位置。读取旧值(用于更新运行平均值)后,将其替换为最新值并增加缓冲区位置(如果为 99,则将其设置回 0 ......因此,循环部分)。
将其与双向链表进行比较并没有任何意义。循环缓冲区当然可以用双向链表(甚至单链表)来实现。但是比较它们有点像比较苹果和橘子。
我知道这是作弊,但维基百科确实有很好的解释。
http://en.wikipedia.org/wiki/Circular_buffer
循环缓冲区、循环缓冲区或环形缓冲区是一种使用单个固定大小缓冲区的数据结构,就好像它是端到端连接的一样。这种结构很容易缓冲数据流
一个可能使用覆盖循环缓冲区的示例是多媒体。如果缓冲区被用作生产者-消费者问题中的有界缓冲区,那么如果消费者(例如,声卡)暂时无法跟上,生产者(例如,音频发生器)可能希望覆盖旧数据. 另一个例子是数字波导合成方法,它使用圆形缓冲器来有效地模拟振动弦或管乐器的声音。
关于与双链表的比较,我想它确实取决于您使用列表的目的......循环缓冲区的实现似乎更复杂,请(再次)参考维基页面;这解释了实现、注意事项等,还显示了示例代码。
谢谢,尼尔
我用它作为实现循环调度的简单方法。基本上,我有一堆不同的对象可以产生消费者可以处理的值。我把所有的制作人都围成一圈,依次询问每个人。