page contents

C语言 ringBuffer 实现

本文讲述了C语言 ringBuffer 实现!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

attachments-2022-08-9OJrD7Ov62f1bcc786bda.png

本文讲述了C语言 ringBuffer 实现!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

一、 ringBuffer 介绍

ringBuffer 称作环形缓冲,也有叫 circleBuffer 的。就是取内存中一块连续的区域用作环形缓冲区的数据存储区。这块连续的存储会被反复使用,向 ringBuffer 写入数据总是从写指针的位置开始,如写到实际存储区的末尾还没有写完,则将剩余的数据从存储区的头开始写;从该 ringBuffer 读出数据也是从读指针的位置开始,如读到实际存储区的末尾还没有读完,则从存储区的头开始读剩下的数据。

为了保证写入的数据不会覆盖 ringBuffer 里还没有被读出的数据,以及读出的数据不是已经读出过的旧数据,需要使用一个变量 btoRead 表示该 ringBuffer 中有效的数据。使用变量 length 表示该环形缓冲区中真实的缓冲大小。使用指针 source 指向实际的缓存地址。

使用 ringBuffer 读写数据,要确保读写数据的速率和实际缓冲区大小的匹配。如果不匹配,可能会导致溢出,比如读数据太慢,而写数据很快,实际的缓存区又太小,导致整个缓冲区都是还没有被读出的数据,此时新的数据就无法写入。正确使用 ringBuffer 可以保证数据的连续,降低读模块和写模块之间的耦合性。更多关于生产者-消费者模型的知识可以看这篇博客。

二、代码

ringBuffer 的结构体

typedefstruct {
    uint8_t *source;
    uint32_t br;
    uint32_t bw;
    uint32_t btoRead;
    uint32_t length;
}ringbuffer_t;

创建 ringBuffer 函数

voidcreate_ringBuffer(ringbuffer_t *ringBuf, uint8_t *buf, uint32_t buf_len)
{
    ringBuf->br         = 0;
    ringBuf->bw         = 0;
    ringBuf->btoRead    = 0;
    ringBuf->source     = buf;
    ringBuf->length     = buf_len;
    printf("create ringBuffer->length = %d\n", ringBuf->length);
}

清空 ringBuffer 函数

voidclear_ringBuffer(ringbuffer_t *ringBuf)
{
    ringBuf->br         = 0;
    ringBuf->bw         = 0;
    ringBuf->btoRead    = 0;

    //no need do this casue r_ptr and w_prt has change
//  memset((uint8_t *)ringBuf->source, 0, ringBuf->length); 
}

读数据函数

uint32_twrite_ringBuffer(uint8_t *buffer, uint32_t size, ringbuffer_t *ringBuf)
{
    uint32_t len            = 0;
    uint32_t ringBuf_bw     = ringBuf->bw;
    uint32_t ringBuf_len    = ringBuf->length;
    uint8_t *ringBuf_source = ringBuf->source;

    if( (ringBuf_bw + size) <= ringBuf_len  )
    {
        memcpy(ringBuf_source + ringBuf_bw, bufff, size);
    }
    else
    {
        len = ringBuf_len - ringBuf_bw;
        memcpy(ringBuf_source + ringBuf_bw, buffer, len);
        memcpy(ringBuf_source, buffer + ringBuf_bw, size - len);
    }

    ringBuf->bw = (ringBuf->bw + size) % ringBuf_len;
    ringBuf->btoRead += size;

    return size;
}

写数据函数

uint32_tread_ringBuffer(uint8_t *buffer, uint32_t size, ringbuffer_t *ringBuf)
{
    uint32_t len            = 0;
    uint32_t ringBuf_br     = ringBuf->br;
    uint32_t ringBuf_len    = ringBuf->length;
    uint8_t *ringBuf_source = ringBug->source;

    if( (ringBuf_br + size ) <= ringBuf_len )
    {
        memcpy(buffer, ringBuf_source + ringBuf_br, size);
    }
    else
    {
        len = ringBuf_len - ringBuf_br;
        memcpy(bufff, ringBuf_source + ringBuf_br, len);
        memcpy(buffer + len, ringBuf_source, size - len);
    }

    ringBuf->br = (ringBuf->br + size) % ringBuf_len;
    ringBuf->btoRead -= size;

    return size;
}

获取 ringBuffer 中的有效数据

uint32_tget_ringBuffer_btoRead(ringbuffer_t *ringBuf)
{
    return ringBuf->btoRead;
}

获取 ringBuffer 的长度

uint32_tget_ringBuffer_length(ringbuffer_t *ringBuf)
{
    return ringBuf->length;
}

三、使用方法

对 ringBuffer 的使用,首先需要又一块真实并且连续的数据存储区。可以使用 malloc 从堆区分配,也可以使用一个数组。

在写数据之前,需要对此时 ringBuffer 的剩余空间和要写入数据的大小进行比较。剩余空间使用长度 length 减去待读出数据量 btoRead 得到。

在读出数据之前,则需要对此时 ringBuffer 可读出的有效数据 btoRead 进行判断。

读出的数据不够,或者没有足够的空间写如数据,可以在调用读写函数之前进行判断,假如情况不满足,就不调用相应的读写函数。

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

  • 发表于 2022-08-09 09:48
  • 阅读 ( 391 )
  • 分类:C/C++开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章