关于环形缓冲区(ringbuffer)的使用安全

一.preface

看过许多文章,关于ringbuffer在多线程环境下的使用,或者在中断写、thread读的情况下的使用,一般都是需要加锁,来保证同步。
但是在我开发项目的过程中,发现ringbuffer的读写并不需要加锁,资源也不会有竞争。

二.analysis

环形缓冲区是在一端写,另一端读;写完更新write_index, 读完更新read_index.
以读操作为例,进行分析。

点击查看代码
/**************C************/
int8_t ringbuffer_read(uint8_t *ch, ringbuffer_t *rb)
{
    if (rb->read_index == rb->write_index) // 读写指针的位置相等时,说明 ringbuffer 为空。
    {
        return ERR_BUF_EMPTY;
    }
    else
    {
        *ch = rb->buffer_ptr[rb->read_index];
        rb->read_index = (rb->read_index + 1) % rb->buffer_size;
        return ERR_OK;
    }
}

/**************汇编************/
ringbuffer_read
    0x010020b8:    b510        ..      PUSH     {r4,lr}     //函数入口,保存寄存器 r4 和 lr 到栈中,以保护函数调用时的上下文。
/* uint8_t *ch, ringbuffer_t *rb */
    0x010020ba:    460c        .F      MOV      r4,r1       //将 r1(第二个参数 rb)的值移动到 r4 中,方便后续操作。
/* if (rb->read_index == rb->write_index) */
    0x010020bc:    6809        .h      LDR      r1,[r1,#0]  // 加载 rb->read_index 到 r1
    0x010020be:    6862        bh      LDR      r2,[r4,#4]  // 加载 rb->write_index 到 r2
    0x010020c0:    4291        .B      CMP      r1,r2       // 比较 r1 和 r2
    0x010020c2:    d101        ..      BNE      0x10020c8 ; ringbuffer_read + 16  // 如果不相等,跳转到缓冲区不为空的处理
/* return ERR_BUF_EMPTY; */
    0x010020c4:    2008        .       MOVS     r0,#8        // 将返回值 ERR_BUF_EMPTY (8) 放入 r0
    0x010020c6:    bd10        ..      POP      {r4,pc}      // 恢复寄存器并返回
/* *ch = rb->buffer_ptr[rb->read_index]; */
    0x010020c8:    6822         h      LDR      r2,[r4,#0]   // 重新加载 rb->read_index 到 r2
    0x010020ca:    68e1        .h      LDR      r1,[r4,#0xc] // 加载 rb->buffer_ptr 到 r1
    0x010020cc:    5c89        .\      LDRB     r1,[r1,r2]   //读取一个字节到 r1
    0x010020ce:    7001        .p      STRB     r1,[r0,#0]   // 将 r1 的值存储到 *ch
/* rb->read_index = (rb->read_index + 1) % rb->buffer_size; */
    0x010020d0:    68a1        .h      LDR      r1,[r4,#8]
    0x010020d2:    6820         h      LDR      r0,[r4,#0]
    0x010020d4:    1c40        @.      ADDS     r0,r0,#1
    0x010020d6:    f7feffe3    ....    BL       __aeabi_uidiv ; 0x10010a0
    0x010020da:    6021        !`      STR      r1,[r4,#0]
/* return ERR_OK; */
    0x010020dc:    2000        .       MOVS     r0,#0
    0x010020de:    bd10        ..      POP      {r4,pc}

三.conclusions

posted @ 2025-04-03 18:04  Charles_hui  阅读(60)  评论(0)    收藏  举报