很久以前就想说一说这哥仨的区别了,可是奈何懒癌间歇性发作,对这个task是视而不见,汗颜。。好了,废话不说了,进入正题。
首先,先看最基础的队列:
队列嘛,内部使用数组实现的话,无非是从头部读取,在尾部插入
但是有一个缺点,就是队列经过若干次的读取后,前面明明还有空间,却不能再使用了
解决这个问题的直观办法就像这样
就是每删除一个头,后面的所有元素往前移动一位。现实生活中的确是这样,前面的人走了,后面的人顶上去。
但是,这个方法是有问题的,这种方法带来了复制元素的开销,当队列很大时,将会带来严重的性能问题。
因此,为了解决这个问题,循环队列(也叫循环缓冲区)应运而生。其特点是,使用读指针和写指针来完成队列头和队列尾部的判断
这样就没有了复制元素带来的开销了,本质上还是对一个队列的读写过程的优化和改进。
那么乒乓缓冲区又是什么鬼呢,它对应的是个什么场景呢?
我们思考这样一件事,串口的数据通过DMA搬到一个buffer里面,然后在搬运的过程没有结束的时候,一般不能操作这个buffer,只有等搬运完毕
等到DMA中断才可以进行操作。但是,这段时间CPU相当于就被浪费掉了,啥事也没干。这显然是算力的浪费(这里指的是单任务环境下),而且,CPU开始处理后,
那下一帧数据又来了咋办呢,毕竟我们又不能预料什么时候会发生串口中断,那上一帧数据岂不是被破坏了吗?这个时候有人可能说了,你整个队列不就行了吗。
的确,这是一个解决办法。
网上找的一段话提供了另一个思路
具体过程是:当串口 BUF1 满了时,DMA 的目标地址迅速切换到 BUF2,此时可以处理
BUF1 的数据;当串口 BUF2 满了时,DMA 的目标地址迅速切换到 BUF1,此时可以处理 BUF2的数据。如此一直循环下去,就像打乒乓球一样,你推我挡,故称作乒乓缓冲
这就是乒乓缓冲区的原理,但是,其实,我认为这里还有一个问题没有指出来,那就是,buff2满了的时候,要切换到buff1,那如果这个时候buf1还没有处理完成怎么办呢?
所以我觉得还是应该用队列来处理上面的这个场景。不知道作为读者的你有何看法,反正我觉得上面的引用里的说辞不能说服我。如果有更好的解释,欢迎在下方留言或评论。
来源:https://www.cnblogs.com/Arnold-Zhang/p/12045476.html