什么是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

 

posted @ 2026-01-28 17:45  沙特西  阅读(1)  评论(0)    收藏  举报