1、前言 ring buffer是一种固定尺寸、头尾相连的缓冲池的数据结构,适合缓存数据流。环形缓冲池多用于两个任务之间传递数据,是标准的先入先出模型。 一般来说,若多个任务之间共享数据需要使用互斥机制来进行同步,以保证共享数据不会发生不可预测的修改与读取,然而互斥机制的使用也会带来额外的系统开销。环形缓冲池的引入就是为了有效解决这个问题,以提高系统资源利用率。 2、初始化与重置(1)ring buffer初始化 函数原型:kstart_t krhino_ringbuf_init(k_ringbuf_t *p_ringbuf, void *buf, size_t len,size_t type, size_t block_size) ring buffer初始化需配置ringbuf的长度、类型、存储元素长度及在内存中实际的存储位置。其中,管理结构体k_ringbuf_t的主要数据成员包括: buf:ring buffer在内存中的实际开始位置; end:ring buffer在内存中的实际结束位置; head:存储在缓冲池中的有效数据的开始位置,即读指针; tail:存储在缓冲池中的有效数据结尾位置,即写指针; freesize:标示缓冲池当前剩余可用空间大小; type:标示缓冲池的内型,“固定长度(RINGBUF_TYPE_FIX)或是可变长度(RINGBUF_TYPE_DYN)”。 block_size:标示存储在缓冲池中的单个数据块长度,只针对RINGBUF_TYPE_FIX有效。 (2)ring buffer重置 函数原型:kstart_t krhino_ring.buf_reset(k_ringbuf_t *p_ringbuf) ring buffer重置会清除缓冲池中的数据块,并重置ring buffer的读/写指针、剩余可用空间大小。 3、环形缓冲池的写入与读取(1)ring buffer的写入 函数原型:kstart_t krhino_ringbuf_push(k_ringbuf_t *p_ringbuf, void *data,size_t len) ring buffer写入的步骤主要包括: ①判断缓冲池是否已满,若已满,则返回RHINO_RINGBUF_FULL错误。 ②判断缓冲池的剩余空间能否写入数据块,若不能,则返回RHINO_RINGBUF_FULL错误。 ③重新校准缓冲池的写指针及剩余空间大小。 ④压入数据块。 ring buffer写入流程如下图所示: (2)ring buffer的读取 函数原型:kstat_t krhino_ringbuf_pop(k_ringbuf_t *p_ringbuf, void *pdata, size_t *plen) ring buffer读取的步骤包括: ①判断缓冲池是否为空,若为空,则返回RHINO_RINGBUF_EMPTY错误; ②读取数据块; ③校准缓冲池读指针及剩余空间大小。 ring buffer 读取流程如下图所示: 4、环形缓冲池的容量判断(1)判断ring buffer是否为空 函数原型:uint8_t krhino_ringbuf_is_empty(k_ringbuf_t *p_ringbuf) 若缓冲池的剩余空间大小与预设的环形缓冲池长度一致,会判断此时缓冲池为空。 (2)判断ring buffer是否已满 函数原型:uint8_t krhino_ringbuf_is_full(k_ringbuf_t *p_ringbuf) 对于RINGBUF_TYPE_FIX类型,若环形缓冲池的剩余空间小于预设的固定数据块长度,则判定缓存池已满。对于RINGBUF_TYPE_DYN类型,若环形缓存区的剩余空间小于8字节,则判定缓存池已满。
|