环形存储(ring buffer):一个头尾相连的buffer,根据head索引确定写入位置,根据tail索引确定读出位置,读写时head、tail索引各自递增,不够空间且有新数据要写入时,覆盖旧数据。
下图演示了创建/初始化长度12、写4bytes数据、读2bytes数据时,ring buffer的head、tail索引变化情况。
//因此使用ring buffer关键因素是数据缓冲区、数据缓冲区长度、head索引、tail索引
typedef struct {
char *buff;
int length;
int head;
int tail;
}ring_buffer_t;
//创建、初始化ring buffer
ring_buffer_t *ring_buffer_create_init(int ring_buffer_length)
{
ring_buffer_t *tmp_ring_buffer = (ring_buffer_t *)malloc(sizeof(ring_buffer_t));
tmp_ring_buffer->buff = (char *)malloc(ring_buffer_length);
memset(tmp_ring_buffer->buff, 0, ring_buffer_length);
tmp_ring_buffer->head = 0;
tmp_ring_buffer->tail = 0;
tmp_ring_buffer->length = ring_buffer_length;
return tmp_ring_buffer;
}
//判断当前有无数据可读,用于读操作前的判断
//如果当前要写入的位置和可读位置相同,则判定无数据可读
bool ring_buffer_empty(ring_buffer_t *ring_buffer)
{
return (ring_buffer->head == ring_buffer->tail);
}
//判断当前ring buffer是否满了,用于写操作前的判断
//如果要写的位置紧挨在可读位置后面,则判定为满
bool ring_buffer_full(ring_buffer_t *ring_buffer)
{
int tmp_len = ring_buffer->head - ring_buffer->tail;
if((-1 == tmp_len) || (ring_buffer->length -1 == tmp_len)){
return true;
}else{
return false;
}
}
//写一个字节到ring buffer,如果ring buffer满了head、tail递增,覆盖旧数据
void write_ring_buffer_byte(ring_buffer_t *ring_buffer, char data)
{
//此处控制如果有写入操作后,当写快于读时,head和tail也不会相等,即不会判断无数据可读
if(ring_buffer_full(ring_buffer)){
ring_buffer->tail++;
if(ring_buffer->tail == ring_buffer->length){
ring_buffer->tail = 0;
}
}
ring_buffer->buff[ring_buffer->head] = data;
ring_buffer->head++;
if(ring_buffer->head == ring_buffer->length){
ring_buffer->head = 0;
}
}
//读一个字节
int read_ring_buffer_byte(ring_buffer_t *ring_buffer, char *data)
{
if(ring_buffer_empty(ring_buffer)){
return -1;
}
*data = ring_buffer->buff[ring_buffer->tail];
ring_buffer->tail++;
if(ring_buffer->tail == ring_buffer->length){
ring_buffer->tail = 0;
}
return 0;
}
//写buffer时即一个个字节写
void write_ring_buffer_data(ring_buffer_t *ring_buffer, char *data, int size)
{
for(int i = 0;i < size;i++){
write_ring_buffer_byte(ring_buffer, *(data + i));
//printf("[%s]data:[%s]\n", __func__, ring_buffer->buff);
}
}
//读buffer时即一个个字节读
int read_ring_buffer_data(ring_buffer_t *ring_buffer, char *data, int size)
{
for(int i = 0; i < size; i++){
if(-1 == read_ring_buffer_byte(ring_buffer, data + i)){
return -1;
}
//printf("[%s]read data:[%s]\n", __func__, data);
}
return 0;
}
//测试程序
void main(void)
{
int i;
char tmp_write[20] = "abcdefghijklmnopq";
char tmp_read[20] = {0};
ring_buffer_t *ring_buffer = ring_buffer_create_init(20); //10、50
#if 0
for(i = 0;i < strlen(tmp_write); i++){
write_ring_buffer_byte(ring_buffer, *(tmp_write + i));
printf("write_buff:[%s]\n", ring_buffer->buff);
}
for(i = 0;i < 20; i++){
read_ring_buffer_byte(ring_buffer, tmp_read+i);
printf("read_buff:[%s]\n", tmp_read);
}
#endif
write_ring_buffer_data(ring_buffer, tmp_write, strlen(tmp_write));
printf("[%s]write data:[%s]\n", __func__, ring_buffer->buff);
read_ring_buffer_data(ring_buffer, tmp_read, sizeof(tmp_read));
printf("[%s]read_buff:[%s]\n", __func__, tmp_read);
}