`

RingBuffer - 原理与实现

阅读更多
1. 原理

参考http://blog.chinaunix.net/uid-9407839-id-3954445.html

      环形缓冲区通常有一个读指针和一个写指针。读指针指向环形缓冲区中可读的数据,写指针指向环形缓冲区中可写的缓冲区。通过移动读指针和写指针就可以实现缓冲区的数据读取和写入。在通常情况下,环形缓冲区的读用户仅仅会影响读指针,而写用户仅仅会影响写指针。如果仅仅有一个读用户和一个写用户,那么不需要添加互斥保护机制就可以保证数据的正确性。如果有多个读写用户访问环形缓冲区,那么必须添加互斥保护机制来确保多个用户互斥访问环形缓冲区。

图1、图2和图3是一个环形缓冲区的运行示意图。图1是环形缓冲区的初始状态,可以看到读指针和写指针都指向第一个缓冲区处;图2是向环形缓冲区中添加了一个数据后的情况,可以看到写指针已经移动到数据块2的位置,而读指针没有移动;图3是环形缓冲区进行了读取和添加后的状态,可以看到环形缓冲区中已经添加了两个数据,已经读取了一个数据。

 

 

2. 代码实现(以RT-Thread源代码为例)

结构体定义

struct rt_ringbuffer
{
    rt_uint16_t read_index, write_index;
    rt_uint8_t *buffer_ptr;
    rt_uint16_t buffer_size;
};

 

初始化函数

void rt_ringbuffer_init(struct rt_ringbuffer *rb,
                        rt_uint8_t           *pool,
                        rt_uint16_t           size)
{
    RT_ASSERT(rb != RT_NULL);

    /* initialize read and write index */
    rb->read_index = rb->write_index = 0;

    /* set buffer pool and size */
    rb->buffer_ptr = pool;
    rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
}

 

写入函数

rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
                            const rt_uint8_t     *ptr,
                            rt_uint16_t           length)
{
    rt_uint16_t size;
    rt_uint16_t mask;
    rt_uint16_t write_position;
    
    RT_ASSERT(rb != RT_NULL);

    mask = rb->buffer_size - 1;
    /* whether has enough space */
    size = rb->buffer_size - (rb->write_index - rb->read_index);

    /* no space */
    if (size == 0)
        return 0;
    /* drop some data */
    if (size < length)
        length = size;

    write_position = (rb->write_index & mask);
    if (rb->buffer_size - write_position> length)
    {
        /* read_index - write_index = empty space */
        memcpy(&rb->buffer_ptr[write_position], ptr, length);
    }
    else
    {
        memcpy(&rb->buffer_ptr[write_position], ptr,
               rb->buffer_size - write_position);
        memcpy(&rb->buffer_ptr[0], &ptr[rb->buffer_size - write_position],
               length - (rb->buffer_size - write_position));
    }
    rb->write_index += length;

    return length;
}

  其中

mask = rb->buffer_size - 1;
read_position = rb->read_index & mask;

 是可以实现写指针绕回到缓冲区头部后归0,注意该操作需要在获得size后才能执行。size为缓冲区空余的空间,若需要写入的数据长度超出size,则截断。若数据长度大于缓冲区尾部到当前写指针的长度,则需分两次写入操作。

 

 读出函数

rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
                            rt_uint8_t           *ptr,
                            rt_uint16_t           length)
{
    rt_size_t size;
    rt_uint16_t mask;
    rt_uint16_t read_position;

    RT_ASSERT(rb != RT_NULL);
    /* whether has enough data  */
    mask = rb->buffer_size - 1;
    size = rb->write_index - rb->read_index;

    /* no data */
    if (size == 0)
        return 0;
    /* less data */
    if (size < length)
        length = size;

    read_position = rb->read_index & mask;
    if (rb->buffer_size - read_position >= length)
    {
        /* copy all of data */
        memcpy(ptr, &rb->buffer_ptr[read_position], length);
    }
    else
    {
        /* copy first and second */
        memcpy(ptr, &rb->buffer_ptr[read_position],
               rb->buffer_size - read_position);
        memcpy(&ptr[rb->buffer_size - read_position], &rb->buffer_ptr[0],
               length - rb->buffer_size + read_position);
    }
    rb->read_index += length;

    return length;
}

其中size为当前缓冲区中含有数据的长度,若需要读出的数据长度超出size,则截断。若数据长度大于尾部到当前读指针的长度,则需分两次读取操作。

 

 

 

分享到:
评论

相关推荐

    ring buffer实现原理

    1、环形缓冲区的实现原理 环形缓冲区通常有一个读指针和一个写指针。读指针指向环形缓冲区中可读的数据,写指针指向环形缓冲区中可写的缓冲区。通过移动读指针和写指针就可以实现缓冲区的数据读取和写入。在通常情况...

    ringbuffer - 原创-高效率管理

    原创ringbuffer:具有高效率管理块传输,动态内存分配释放。自适应char8,int16, int32数据类型。

    netty-buffer-4.1.68.Final-API文档-中文版.zip

    赠送jar包:netty-buffer-4.1.68.Final.jar; 赠送原API文档:netty-buffer-4.1.68.Final-javadoc.jar; 赠送源代码:netty-buffer-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-buffer-4.1.68.Final....

    netty-buffer-4.1.73.Final-API文档-中文版.zip

    赠送jar包:netty-buffer-4.1.73.Final.jar; 赠送原API文档:netty-buffer-4.1.73.Final-javadoc.jar; 赠送源代码:netty-buffer-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-buffer-4.1.73.Final....

    前端开源库-buffer-loader

    前端开源库-buffer-loader缓冲加载程序,用于WebPack的缓冲加载程序模块

    netty-buffer-4.1.11.Final-API文档-中文版.zip

    赠送jar包:netty-buffer-4.1.11.Final.jar; 赠送原API文档:netty-buffer-4.1.11.Final-javadoc.jar; 赠送源代码:netty-buffer-4.1.11.Final-sources.jar; 赠送Maven依赖信息文件:netty-buffer-4.1.11.Final....

    netty-buffer-4.1.23.Final-API文档-中文版.zip

    赠送jar包:netty-buffer-4.1.23.Final.jar; 赠送原API文档:netty-buffer-4.1.23.Final-javadoc.jar; 赠送源代码:netty-buffer-4.1.23.Final-sources.jar; 赠送Maven依赖信息文件:netty-buffer-4.1.23.Final....

    netty-buffer-4.1.65.Final-API文档-中文版.zip

    赠送jar包:netty-buffer-4.1.65.Final.jar; 赠送原API文档:netty-buffer-4.1.65.Final-javadoc.jar; 赠送源代码:netty-buffer-4.1.65.Final-sources.jar; 赠送Maven依赖信息文件:netty-buffer-4.1.65.Final....

    netty-buffer-4.1.73.Final-API文档-中英对照版.zip

    赠送jar包:netty-buffer-4.1.73.Final.jar; 赠送原API文档:netty-buffer-4.1.73.Final-javadoc.jar; 赠送源代码:netty-buffer-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-buffer-4.1.73.Final....

    RingBuffer 循环缓存 亲测可用 V2 修改一处

    运用技术: C++ 11 ,thread ,atomic ,mutex ,condition_variable 。 程序特性: 1.每个实例支持读写双线程。... 支持windows平台的vs与linux平台的clion,语言级别实现,与平台无关。 附件是代码工程,已编译。

    Rt-thead studio软件下使用ringbuffer

    Rt-thead studio软件下使用ringbuffer

    netty-buffer-4.1.27.Final-API文档-中文版.zip

    赠送jar包:netty-buffer-4.1.27.Final.jar; 赠送原API文档:netty-buffer-4.1.27.Final-javadoc.jar; 赠送源代码:netty-buffer-4.1.27.Final-sources.jar; 赠送Maven依赖信息文件:netty-buffer-4.1.27.Final....

    ring-buffer-design.rar_V2 _buffer_ring_buffer

    Lockless Ring Buffer Design for Linux v2.13.6.

    netty-buffer-4.1.11.Final-API文档-中英对照版.zip

    赠送jar包:netty-buffer-4.1.11.Final.jar; 赠送原API文档:netty-buffer-4.1.11.Final-javadoc.jar; 赠送源代码:netty-buffer-4.1.11.Final-sources.jar; 赠送Maven依赖信息文件:netty-buffer-4.1.11.Final....

    nd4j-buffer-1.0.0-alpha-API文档-中文版.zip

    赠送jar包:nd4j-buffer-1.0.0-alpha.jar; 赠送原API文档:nd4j-buffer-1.0.0-alpha-javadoc.jar; 赠送源代码:nd4j-buffer-1.0.0-alpha-sources.jar; 赠送Maven依赖信息文件:nd4j-buffer-1.0.0-alpha.pom; ...

    netty-buffer-4.1.24.Final-API文档-中文版.zip

    赠送jar包:netty-buffer-4.1.24.Final.jar; 赠送原API文档:netty-buffer-4.1.24.Final-javadoc.jar; 赠送源代码:netty-buffer-4.1.24.Final-sources.jar; 赠送Maven依赖信息文件:netty-buffer-4.1.24.Final....

    Lock-free Queue and Ring Buffer

    Lock-free Queue and Ring Buffer

    nd4j-buffer-1.0.0-alpha-API文档-中英对照版.zip

    赠送jar包:nd4j-buffer-1.0.0-alpha.jar; 赠送原API文档:nd4j-buffer-1.0.0-alpha-javadoc.jar; 赠送源代码:nd4j-buffer-1.0.0-alpha-sources.jar; 赠送Maven依赖信息文件:nd4j-buffer-1.0.0-alpha.pom; ...

    netty-buffer-4.1.16.Final-API文档-中文版.zip

    赠送jar包:netty-buffer-4.1.16.Final.jar; 赠送原API文档:netty-buffer-4.1.16.Final-javadoc.jar; 赠送源代码:netty-buffer-4.1.16.Final-sources.jar; 赠送Maven依赖信息文件:netty-buffer-4.1.16.Final....

    buffer-overflow-attack

    buffer-overflow-attack.pdf buffer-overflow-attack.pdf

Global site tag (gtag.js) - Google Analytics