最近研究驱动框架,顺带研读了ringbuffer源代码,发现一处疑问,个人认为是bug,也可能能力有限分析不对,请各位大佬批评指正,代码如下:
rt_ringbuffer_put_force
函数,向buffer中put数据的策略为:
1)如果数据长度length > buffer_size,
就将数据截断,只留后面的buffer_size
长度的数据,从下面代码可以看出来:
2)space_length为空闲区长度,如果length > space_length
,就将buffer中老的数据覆盖掉。
的确,rt_ringbuffer_put_force
是按照上面两条策略在put数据,但是代码到下面这几行,存在问题了:
这里是一条华丽的分界线
这里是length >= buffer_size - write_index
的情况,不然前面的代码直接return了。针对这种情况:
write_index
一定会溢出(也就是会超过buffer_size
),这个时候一定有write_mirror = ~write_mirror
。(问题来了:read_index
是否会溢出?这得分情况讨论,看下面2)length > space_length, read_index
就一定会超过buffer_size???,我认为不一定 ),下面讨论:write_index < read_index
,这种情况下,空闲区域在缓冲区中间,有数据的区域在缓冲区两头,这种情况下,read_index和write_index都会溢出,因此有:read_mirror = ~read_mirror
read_index < write_index
,这种情况,有数据区域在缓冲区中间,缓冲区两头是空闲的,这个时候,write_index一定会溢出,但是read_index却不会溢出(因为前面限定了length最大不会超过buffer_size),这种情况下,read_mirror不变。
附一张截图,供大家理解我的意思:
所以我认为应该这样改:
大家认为呢?
@RongLiu 先表一表楼主,可以的,很细心。?
首先这个不叫溢出,这个叫回环,环形buffer的回环属于正常操作。(而溢出是致命的错误,溢出有标准的解释和处理手段,不要乱起名字)。
然后是这个 情况1
,分析的很有道理,write_index
回环的时候,read_index
不一定会触发回环,这个时候如果强行将 read_mirror
取反,则会导致 环形缓冲区的数据长度清空,而不是满。
最后是关于楼主修改的部分是有问题的,应该这样改
应该充分考虑当length > space_length
时候的情况,也就是情况1和情况2,显然楼主分析完之后,代码没有考虑情况2.
另外提供一份测试代码,方便测试:
厉害了,谁来把测试用例提交上来?
https://github.com/RT-Thread/rt-thread/tree/master/examples/utest
@123 谢谢你的耐心解答,分析十分到位,所见略同,我虽然分析出了这个bug,但最后在代码改动上确实考虑不全面。
关于“溢出”这个词,我本意是
write_index
和read_index
超过了缓冲区边界,为什么用这个词,也是看到原来代码作者的注释使用了overflow
一词,故用之,谢谢你指出这个说法的不严谨之处。最后总结下:
讨论
length > space_length
,是为了判断是否要修改read_index
,至于read_mirror是否需要修改,只有在情况1时候才需要修改。其实也就是你说的“充分考虑
length > space_length
时的情况”