ring buffer简单原理及c代码实现

环形存储(ring buffer):一个头尾相连的buffer,根据head索引确定写入位置,根据tail索引确定读出位置,读写时head、tail索引各自递增,不够空间且有新数据要写入时,覆盖旧数据。
下图演示了创建/初始化长度12、写4bytes数据、读2bytes数据时,ring buffer的head、tail索引变化情况。
ring buffer简单原理及c代码实现

//因此使用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);
}
上一篇:【网络】云计算网络名词解释


下一篇:boost::geometry::ring_type用法的测试程序