什么是ring buffer?
1、什么是ring buffer?
环形缓冲区(ring buffer),是一种基于数组的循环队列。其特点是首尾相连,形成一个环状结构。
ring buffer包含两个主要的指针(head、tail):
- head指针:指向队列的第一个有效数据的位置。
- tail指针:指向队列的下一个可写入的位置。(当tail指针到达数组的末尾时,它会绕到数组的开头继续写入,从而形成一个环形)
2、代码实现(C语言)
(缺点:下述代码,未实现overwrite,即当缓存区满时,覆盖旧数据)
#include <stdlib.h> #include <stdbool.h> #include <stdint.h> typedef struct { uint8_t *buffer; size_t head; size_t tail; size_t size; bool full; } ringbuffer_t; /** * Initialize&&Free ringbuffer */ void ringbuffer_init(ringbuffer_t *rb, size_t size){ if(rb == NULL || size == 0){ return; } rb->buffer = (uint8_t *)malloc(size); if(rb->buffer == NULL){ // malloc error return; } rb->head = 0; rb->tail = 0; rb->size = size; rb->full = false; } void ringbuffer_free(ringbuffer_t *rb){ free(rb->buffer); } /** * Get ringbuffer status */ bool ringbuffer_is_full(const ringbuffer_t *rb){ return rb->full; } bool ringbuffer_is_empty(const ringbuffer_t *rb){ return (!rb->full&&(rb->head == rb->tail)); } size_t ringbuffer_available_data(const ringbuffer_t *rb){ if(rb->full){ return rb->size; } return (rb->head >= rb->tail) ? (rb->head-rb->tail) : (rb->size-rb->tail+rb->head); } size_t ringbuffer_available_space(const ringbuffer_t *rb){ return rb->size - ringbuffer_available_data(rb); } /** * Write&&Read ringbuffer */ void ringbuffer_write(ringbuffer_t *rb, const uint8_t *data, size_t len){ if(len > ringbuffer_available_space(rb)) { return; } for(size_t i=0; i<len; i++) { rb->buffer[rb->head] = data[i]; rb->head = (rb->head+1) % rb->size; } if(rb->head == rb->tail) { rb->full = true; } } void ringbuffer_read(ringbuffer_t *rb, uint8_t *data, size_t len){ if(len > ringbuffer_available_data(rb)) { return; } for(size_t i=0; i<len; i++) { data[i] = rb->buffer[rb->tail]; rb->tail = (rb->tail+1) % rb->size; } rb->full = false; }
3、测试代码(C语言)
#include <stdio.h> #include "ringbuffer.c" int main() { ringbuffer_t buffer; ringbuffer_init(&buffer, 10); printf("Available space: %zu\n", ringbuffer_available_space(&buffer)); printf("Available data: %zu\n", ringbuffer_available_data(&buffer)); //write uint8_t write_data[] = {1, 2, 3, 4, 5}; printf("\nWriting data: "); for(int i = 0; i < 5; i++) { printf("%d ", write_data[i]); } printf("\n"); ringbuffer_write(&buffer, write_data, 5); printf("After writing - Available data: %zu, Available space: %zu\n", ringbuffer_available_data(&buffer), ringbuffer_available_space(&buffer)); //read uint8_t read_data[5];
ringbuffer__read(&buffer, read_data, 3);
printf("Read 3 bytes: "); for(int i = 0; i < 3; i++) { printf("%d ", read_data[i]); } printf("\n");
printf("Final - Available data: %zu, Available space: %zu\n", ringbuffer_available_data(&buffer), ringbuffer_available_space(&buffer)); ringbuffer_free(&buffer); return 0; }
~/workspace$ gcc -o test main.c ~/workspace$ ./test Available space: 10 Available data: 0 Writing data: 1 2 3 4 5 After writing - Available data: 5, Available space: 5 Read 3 bytes: 1 2 3 Final - Available data: 2, Available space: 8
参考文献:
https://zhuanlan.zhihu.com/p/712832676
https://zhuanlan.zhihu.com/p/25730907114

浙公网安备 33010602011771号