总缓存大小size要求必须是2的指数倍。
实际能使用的最大缓存数是size-1。
入缓存移动head,出队列移动tail。
队列判空的条件为 head==tail 。
队列判满的条件为 (head+1) % size == tail 。
单个缓存位置操作时无论h或t操作完成后下一个位置可使用如下宏计算得到: #define NEXT_POS(x) ((x+1) % size)
连续缓存位置操作时可以使用如下内核定义的CIRC_x_TO_END配合CIRC_x进行操作。
/* SPDX-License-Identifier: GPL-2.0 */
/*
* See Documentation/core-api/circular-buffers.rst for more information.
*/
#ifndef _LINUX_CIRC_BUF_H
#define _LINUX_CIRC_BUF_H 1
struct circ_buf {
char *buf;
int head;
int tail;
};
/* Return count in buffer. *//* 缓存中已经存在的数据总量 */
#define CIRC_CNT(head,tail,size) (((head) - (tail)) & ((size)-1))
/* Return space available, 0..size-1. We always leave one free char
as a completely full buffer has head == tail, which is the same as
empty. *//* 缓存中空闲的数据总量 */
#define CIRC_SPACE(head,tail,size) CIRC_CNT((tail),((head)+1),(size))
/* Return count up to the end of the buffer. Carefully avoid
accessing head and tail more than once, so they can change
underneath us without returning inconsistent results. */
/* 缓存中可连续取出的数据量(memcpy),当h>t时已存入的数据位置在缓存中单调此量可从t开始将缓存取
空;当h<t时已存数据位置被数组头尾分成两部分,从t开始取此量只是部分数据,另一部分数据量是缓
存中数据总量减去该量,可以从缓存的0位置继续连续取出 */
#define CIRC_CNT_TO_END(head,tail,size) \
({int end = (size) - (tail); \
int n = ((head) + end) & ((size)-1); \
n < end ? n : end;})
/* Return space available up to the end of the buffer. */
/* 换存中可以连续写入的数据量(memcpy),当h>t时空闲数据位置被数组头尾分成两个部分,从h开始写此量
只是部分数据,另一部分数据量是缓存中空闲的数据总量减去该量,可以从缓存的0位置继续连续写入;当
h<t时空闲数据位置单调,此量可以将缓存从h位置直接写满 */
#define CIRC_SPACE_TO_END(head,tail,size) \
({int end = (size) - 1 - (head); \
int n = (end + (tail)) & ((size)-1); \
n <= end ? n : end+1;})
#endif /* _LINUX_CIRC_BUF_H */