# ring_buffer_memory_pool **Repository Path**: schips/ring_buffer_memory_pool ## Basic Information - **Project Name**: ring_buffer_memory_pool - **Description**: 基于ring_buffer的fifo机制内存池 - **Primary Language**: C - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 3 - **Created**: 2020-10-28 - **Last Updated**: 2023-07-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Ring_buffer_memory_pool 一个基于环形缓冲区实现的内存池。 内部由单链表实现。 ## 介绍 ### 应用场景 工作队列中,按顺序地申请、释放有关的内存时,这个环形缓冲区就能够派上用场。 例如: 在中断中接收数据,申请内存、拷贝数据以后,交给任务队列;任务队列从中取出最早的内存,并做处理。 ### 特性 紧凑的内存分布(需要严格注意指针访问不能越界)。 申请释放的开销为O(1)。 开销小: 每块内存 额外开销为 24 个字节。 允许不同的业务使用,并提供对应的查找方法(name、id);默认从第一个开始池找。 ## 备注 考虑到 这种内存池 的申请释放是按顺序的,因此没有实现 释放指定内存 的 接口。 > 因为这样会造成内存空洞而无法分配;而且也违背了这个组件设计的初衷。 为了实现紧凑的内存池,因此,块 与 块 之间是紧挨着的。 > 内存分布为: 块1信息+块1内存+块2信息+块2内存+... 考虑到跨平台的需要,没有实现临界区保护(多线程环境需要格外注意)。 ## 原理 使用指针来管理 以下关键数据: - 第一次创建的内存块`first`:用于获取以及使用内存块 - 最新(最后)创建的内存块`newest`:用来实现尾插法 - 实际的内存区域信息`pool`: - 所使用的内存地址`addr`:从中分配内存出去 - 分配用的写指针`w_ptr`:每次分配时,指针前进对应的位置。 ### 申请内存 创建的内存块会依次通过链表的形式链接起来,形成一条单链表。 而为了确保申请的内存能够高效地按申请顺序的依次排序(FIFO),因此使用了一个指针来记录最后一个节点的位置。 这样,插入的效率始终是O(1)。 ### 释放内存 因为记录了第一个内存块的地址,因此,只需要在释放时,将记录的节点向后移动即可。 **始终释放最早创建的内存块。** ### 注意事项 环形缓冲区的实现本身非常简单,但是为了将其作为内存池,则需要注意内存截断的问题。 当可供分配的地址增长,即将到达缓冲区尾部时;如果此时申请的长度大于 当前位置到缓冲区尾部 的 间隙时,应该考虑将分配用的指针复位到缓冲区头部,再做计算剩余空间是否满足要求。 ## TODO 1、动态地水平拓展环形缓冲区:`struct ring_buffer`中添加链表节点`next`、`prev`,达到在缓冲区之间分配内存。(同样需要注意内存截断的问题) > 适用于将多个小内存组成一片逻辑上的"大"内存