可以看一下這篇我寫(xiě)的博客,了解一下大概:?
RingBuffer 環(huán)形緩沖區(qū)----鏡像指示位_呵呵噠( ̄▽?zhuān)?"的博客-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/132340883?spm=1001.2014.3001.5501
【回顧】緩沖區(qū)變滿(mǎn)在環(huán)形緩沖區(qū)(ring buffer)中會(huì)實(shí)際發(fā)生,一般會(huì)有兩種處理策略:
??????????① 覆蓋老數(shù)據(jù)
??????????② 拋出“異?!?/p>
鏡像指示位:緩沖區(qū)的長(zhǎng)度如果是n,邏輯地址空間則為0至n-1;那么,規(guī)定n至2n-1為鏡像邏輯地址空間。本策略規(guī)定讀寫(xiě)指針的地址空間為0至2n-1,其中低半部分對(duì)應(yīng)于常規(guī)的邏輯地址空間,高半部分對(duì)應(yīng)于鏡像邏輯地址空間。當(dāng)指針值大于等于2n時(shí),使其折返(wrapped)到ptr-2n。使用一位表示寫(xiě)指針或讀指針是否進(jìn)入了虛擬的鏡像存儲(chǔ)區(qū):置位表示進(jìn)入,不置位表示沒(méi)進(jìn)入還在基本存儲(chǔ)區(qū)。
? ? ? ? 在讀寫(xiě)指針的值相同情況下,如果二者的指示位相同,說(shuō)明緩沖區(qū)為空;如果二者的指示位不同,說(shuō)明緩沖區(qū)為滿(mǎn)。這種方法優(yōu)點(diǎn)是測(cè)試緩沖區(qū)滿(mǎn)/空很簡(jiǎn)單;不需要做取余數(shù)操作;讀寫(xiě)線(xiàn)程可以分別設(shè)計(jì)專(zhuān)用算法策略,能實(shí)現(xiàn)精致的并發(fā)控制。缺點(diǎn)是讀寫(xiě)指針各需要額外的一位作為指示位。
? ? ? ? 如果緩沖區(qū)長(zhǎng)度是2的冪,則本方法可以省略鏡像指示位。如果讀寫(xiě)指針的值相等,則緩沖區(qū)為空;如果讀寫(xiě)指針相差n,則緩沖區(qū)為滿(mǎn),這可以用條件表達(dá)式(寫(xiě)指針==(讀指針異或緩沖區(qū)長(zhǎng)度))來(lái)判斷。
----(來(lái)自百度百科)
一、基本步驟
1.數(shù)據(jù)結(jié)構(gòu)
typedef struct ringbuffer
{
uint8 *buffer_ptr;
uint16 read_mirror : 1;
uint16 read_index : 15;
uint16 write_mirror : 1;
uint16 write_index : 15;
/* as we use msb of index as mirror bit, the size should be signed and
* could only be positive. */
uint16 size;
}ringbuff;
?2.緩沖區(qū)初始化
// 緩沖區(qū)初始化
void rb_init(ringbuff *rb,uint8 *pool,uint16 size){
/* initialize read and write index */
rb->read_mirror = rb->read_index = 0;
rb->write_mirror = rb->write_index = 0;
/* set buffer pool and size */
rb->buffer_ptr = pool;
rb->size = DATA_ALIGN_DOWN(size, DATA_ALIGN_SIZE);
}
?3.創(chuàng)建一個(gè)ringbuffer
// 創(chuàng)建一個(gè)ringbuff
ringbuff* rb_create(uint16_t size) {
ringbuff *rb;
uint8_t *pool;
size = DATA_ALIGN_DOWN(size, DATA_ALIGN_SIZE);// 大小做字節(jié)對(duì)齊
rb = (ringbuff *)malloc(sizeof(ringbuff));// 申請(qǐng)內(nèi)存
if (rb == NULL)
goto exit;
pool = (uint8_t *)malloc(size);// 申請(qǐng)數(shù)據(jù)緩沖區(qū)內(nèi)存
if (pool == NULL) {
free(rb);
rb = NULL;
goto exit;
}
rb_init(rb, pool, size);// 初始化 ringbuff
exit:
return rb;
}
?4.銷(xiāo)毀環(huán)形緩沖區(qū)
// 摧毀 ringbuff
void rb_destroy(ringbuff *rb) {
cout<<"銷(xiāo)毀ringbuff~"<<endl;
free(rb->buffer_ptr);
free(rb);// 釋放申請(qǐng)的內(nèi)存
}
二、緩沖區(qū)中填充指定數(shù)據(jù)長(zhǎng)度的數(shù)據(jù)
5.?緩沖區(qū)中填充指定數(shù)據(jù)長(zhǎng)度的數(shù)據(jù)
舉個(gè)例子:(當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事覆蓋緩沖區(qū)原有數(shù)據(jù))
圖1:當(dāng)環(huán)形緩沖區(qū)為空時(shí),讀索引和寫(xiě)索引指向相同的位置(這里初始化為0);
圖2:寫(xiě)操作:想往(rb->buffer_size = 8)緩沖區(qū)中寫(xiě)入15個(gè)元素:123456789ABCDEF,但寫(xiě)入的數(shù)據(jù)長(zhǎng)度(length)超過(guò)緩沖區(qū)空閑長(zhǎng)度(space_length)了。解決方法:RT-Thread(覆蓋老數(shù)據(jù)策略)就是只截取后8位數(shù)據(jù)放入緩沖區(qū)。
可知length=15,space_length=8,滿(mǎn)足length > space_length,讓ptr = &ptr[length - rb->buffer_size]
圖3:由圖2的操作可以得到以上的環(huán)形緩沖區(qū)的數(shù)據(jù)內(nèi)容分布
圖4:讀操作,讀取緩沖區(qū)4個(gè)元素:89AB,修改讀索引
圖5:寫(xiě)操作,寫(xiě)入緩沖區(qū)4個(gè)元素:1234,修改寫(xiě)索引
?圖6:讀操作,讀取緩沖區(qū)4個(gè)元素:CDEF,修改讀索引
??① 當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事覆蓋緩沖區(qū)原有數(shù)據(jù)
/* 緩沖區(qū)中填充指定數(shù)據(jù)長(zhǎng)度的數(shù)據(jù)(當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事覆蓋緩沖區(qū)原有數(shù)據(jù)) */
uint16 rb_put_force(ringbuff *rb,const uint8 *ptr,uint16 length);
// 強(qiáng)制往 ringbuff 寫(xiě)入數(shù)據(jù)
uint16 rb_put_force(ringbuff *rb,const uint8 *ptr,uint16 length) {
uint16 space_length = 0;
space_length = rb_space_len(rb);
// cout<<"ptr: "<<ptr<<endl;
// cout<<"space_length: "<<space_length<<endl;
// cout<<"length: "<<length<<endl;
if (length > space_length) {
ptr = &ptr[length - rb->size];
length = rb->size;
}
// cout<<"ptr: "<<ptr<<endl;
// cout<<"length: "<<length<<endl;
if (rb->size - rb->write_index > length)
{
// cout<<"lailailailai"<<endl;
/* read_index - write_index = empty space */
memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
rb->write_index += length;
if (length > space_length)
rb->read_index = rb->write_index;
return length;
}
memcpy(&rb->buffer_ptr[rb->write_index],
&ptr[0],
rb->size - rb->write_index);
memcpy(&rb->buffer_ptr[0],
&ptr[rb->size - rb->write_index],
length - (rb->size - rb->write_index));
/* we are going into the other side of the mirror */
rb->write_mirror = ~rb->write_mirror;
rb->write_index = length - (rb->size - rb->write_index);
if (length > space_length)
{
rb->read_mirror = ~rb->read_mirror;
rb->read_index = rb->write_index;
}
return length;
}
??②?當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事不覆蓋緩沖區(qū)原有數(shù)據(jù)
/* 緩沖區(qū)中填充指定數(shù)據(jù)長(zhǎng)度的數(shù)據(jù)(當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事不覆蓋緩沖區(qū)原有數(shù)據(jù)) */
uint16 rb_put(ringbuff *rb,const uint8 *ptr,uint16 length);
// 往 ringbuff 寫(xiě)入數(shù)據(jù)
uint16 rb_put(ringbuff *rb,const uint8 *ptr,uint16 length) {
uint16 size = 0;
/* whether has enough space */
size = rb_space_len(rb);// 獲取 ring_buff 中可用空間的大小
/* no space */
if (size == 0)
return 0;// 如果空間不夠 直接返回
/* drop some data */
if (size < length) // 如果緩存區(qū)的空間不夠保存這一次數(shù)據(jù), 則把能夠?qū)懭氲倪@一部分?jǐn)?shù)據(jù)寫(xiě)進(jìn)去
length = size;
/* One-time write */
if (rb->size - rb->write_index > length)
{
/* read_index - write_index = empty space */
memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
rb->write_index += length;
return length;// 返回寫(xiě)入數(shù)據(jù)的長(zhǎng)度
}
/* two-time write */
memcpy(&rb->buffer_ptr[rb->write_index],
&ptr[0],
rb->size - rb->write_index);
memcpy(&rb->buffer_ptr[0],
&ptr[rb->size - rb->write_index],
length - (rb->size - rb->write_index));
/* we are going into the other side of the mirror */
rb->write_mirror = ~rb->write_mirror;
rb->write_index = length - (rb->size - rb->write_index);
return length;
}
6.?緩沖區(qū)中獲取指定長(zhǎng)度的數(shù)據(jù)(返回實(shí)際獲取數(shù)據(jù)的長(zhǎng)度)
/* 緩沖區(qū)中獲取指定長(zhǎng)度的數(shù)據(jù)(返回實(shí)際獲取數(shù)據(jù)的長(zhǎng)度) */
uint16 rb_get(ringbuff *rb,uint8 *ptr,uint16 length);
// 從 ringbuff 獲取數(shù)據(jù)
uint16 rb_get(ringbuff *rb,uint8 *ptr,uint16 length) {
uint16 size = 0;
/* The length of the existing data in the buffer */
size = rb_data_len(rb);
/* no data */
if (size == 0)
return 0;
/* less data */
if (size < length)
length = size;
cout<<"size: "<<size<<" < "<<"length: " << length<<(size < length)<<endl;
if (rb->size - rb->read_index > length)
{
/* copy all of data */
memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
rb->read_index += length;
return length;
}
memcpy(&ptr[0],
&rb->buffer_ptr[rb->read_index],
rb->size - rb->read_index);
memcpy(&ptr[rb->size - rb->read_index],
&rb->buffer_ptr[0],
length - (rb->size - rb->read_index));
/* we are going into the other side of the mirror */
rb->read_mirror = ~rb->read_mirror;
rb->read_index = length - (rb->size - rb->read_index);
return length;
}
7.測(cè)試和打印
void readprint(ringbuff* rb,uint8 buff[]) {
cout<<"讀取數(shù)據(jù):";
int i = 0;
while(buff[i]!='\0') {
cout<<buff[i++];
}
print(rb);
}
void writeprint(ringbuff* rb){
for(int i=0;i<rb->size;i++){
cout<<rb->buffer_ptr[i];
}
print(rb);
}
void test01() {
ringbuff* rb = rb_create(9);
const uint8 p[] = "123456789ABCDEF";
uint32_t len = sizeof(p) / sizeof(char);
cout<<"寫(xiě)入數(shù)據(jù):"<<p<<endl;
// rb_put(rb,p,len-1);
rb_put_force(rb,p,len-1);
writeprint(rb); // 89ABCDEF
uint8 saveBuff[20] = "";
rb_get(rb,saveBuff,4); // 89AB
readprint(rb,saveBuff);
const uint8 p1[] = "1234";
cout<<"寫(xiě)入數(shù)據(jù):"<<p1<<endl;
rb_put_force(rb,p1,4); // 1234CDEF
writeprint(rb);
memset(saveBuff,0,20);
rb_get(rb,saveBuff,4); // CDEF
cout<<"讀取數(shù)據(jù):";
readprint(rb,saveBuff);
// 銷(xiāo)毀ringbuff
rb_destroy(rb);
}
寫(xiě)入數(shù)據(jù):123456789ABCDEF
89ABCDEF
rb->write_index: 0
rb->read_index: 0
rb->write_mirror: 1
rb->read_mirror: 0
rb_data_len: 8
rb_space_len: 0
size: 8 < length: 40
讀取數(shù)據(jù):89AB
rb->write_index: 0
rb->read_index: 4
rb->write_mirror: 1
rb->read_mirror: 0
rb_data_len: 4
rb_space_len: 4
寫(xiě)入數(shù)據(jù):1234
1234CDEF
rb->write_index: 4
rb->read_index: 4
rb->write_mirror: 1
rb->read_mirror: 0
rb_data_len: 8
rb_space_len: 0
size: 8 < length: 40
讀取數(shù)據(jù):讀取數(shù)據(jù):CDEF
rb->write_index: 4
rb->read_index: 0
rb->write_mirror: 1
rb->read_mirror: 1
rb_data_len: 4
rb_space_len: 4
銷(xiāo)毀ringbuff~
三、緩沖區(qū)中填充一個(gè)數(shù)據(jù)
5.?緩沖區(qū)中填充一個(gè)數(shù)據(jù)
舉個(gè)例子:(當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事覆蓋緩沖區(qū)原有數(shù)據(jù))
圖1:依次存入1、2、3、4、5、6、7、8、A、B、C、D、E、F這些字符,直到緩沖區(qū)為滿(mǎn)
圖2:依次讀出單個(gè)字符: 8、9、A、B
??① 當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事覆蓋緩沖區(qū)原有數(shù)據(jù)
/* 緩沖區(qū)中填充一個(gè)數(shù)據(jù)(當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事覆蓋緩沖區(qū)原有數(shù)據(jù)) */
uint16 rb_putchar_force(ringbuff *rb, const uint8 ch);
// 往 ringbuff 強(qiáng)制寫(xiě)入一個(gè)字符
uint16 rb_putchar_force(ringbuff *rb, const uint8 ch) {
enum rb_state old_state = rb_status(rb);// 獲取狀態(tài)
rb->buffer_ptr[rb->write_index] = ch;// 寫(xiě)入數(shù)據(jù)
/* flip mirror */
if (rb->write_index == rb->size-1) {// 檢查當(dāng)前鏡像是不是滿(mǎn)了
rb->write_mirror = ~rb->write_mirror; // 翻轉(zhuǎn)寫(xiě)鏡像
rb->write_index = 0;// 翻轉(zhuǎn)之后設(shè)置下標(biāo)為 0
if (old_state == RINGBUFFER_FULL) {// 如果 ringbuff 的狀態(tài)是滿(mǎn)
rb->read_mirror = ~rb->read_mirror; // 翻轉(zhuǎn)讀鏡像
rb->read_index = rb->write_index; // 設(shè)置讀下標(biāo)和寫(xiě)下標(biāo)一致
}
}else{
rb->write_index++; // 寫(xiě)下標(biāo)加1
if (old_state == RINGBUFFER_FULL)
rb->read_index = rb->write_index;// 如果滿(mǎn),設(shè)置讀下標(biāo)等于寫(xiě)下標(biāo)
}
return 1; // 寫(xiě)入一個(gè)字符,返回1
}
??② 當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事不覆蓋緩沖區(qū)原有數(shù)據(jù)
/* 緩沖區(qū)中填充一個(gè)數(shù)據(jù)(當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事不覆蓋緩沖區(qū)原有數(shù)據(jù)) */
uint16 rb_putchar(ringbuff *rb, const uint8 ch);
// 往 ringbuff 中寫(xiě)入一個(gè)字符
uint16 rb_putchar(ringbuff *rb, const uint8 ch) {
/* whether has enough space */
if (!rb_space_len(rb)) // 沒(méi)有足夠的空間就直接返回了
return 0;
rb->buffer_ptr[rb->write_index] = ch;// 把這個(gè)字符寫(xiě)入到緩沖區(qū)的指定位置
/* flip mirror */
if (rb->write_index == rb->size-1) {// 檢查寫(xiě)入這個(gè)字符后,當(dāng)前鏡像是否寫(xiě)滿(mǎn)
rb->write_mirror = ~rb->write_mirror;// 翻轉(zhuǎn)鏡像
rb->write_index = 0;// 設(shè)置下標(biāo)為0
}else{
rb->write_index++; // 下標(biāo)加1
}
return 1;// 寫(xiě)入一個(gè)字符,返回 1
}
6.?緩沖區(qū)中獲取一個(gè)數(shù)據(jù)(返回實(shí)際獲取數(shù)據(jù)的長(zhǎng)度)
/* 緩沖區(qū)中獲取一個(gè)數(shù)據(jù)(返回實(shí)際獲取數(shù)據(jù)的長(zhǎng)度) */
uint16 rb_getchar(ringbuff *rb, uint8 *ch);
// 從ringbuff 獲取一個(gè)字符
uint16 rb_getchar(ringbuff *rb,uint8 *ch) {
/* ringbuffer is empty */
if (!rb_data_len(rb)) // 檢查 ringbuff 是否為空
return 0;
/* put character */
*ch = rb->buffer_ptr[rb->read_index];// 獲取當(dāng)前讀下標(biāo)的數(shù)據(jù)
if (rb->read_index == rb->size-1) {// 如果當(dāng)前鏡像滿(mǎn)了
rb->read_mirror = ~rb->read_mirror;// 翻轉(zhuǎn)鏡像
rb->read_index = 0; // 設(shè)置讀數(shù)據(jù)的下標(biāo)為0
} else {
rb->read_index++; // 下標(biāo)加1
}
return 1;// 讀取一個(gè)字節(jié),返回1
}
7.測(cè)試和打印
#include "rb.h"
#include "rb.cpp"
void print(ringbuff *rb) {
cout<<endl;
cout<<"rb->write_index: "<<rb->write_index<<endl;
cout<<"rb->read_index: "<<rb->read_index<<endl;
cout<<"rb->write_mirror: "<<rb->write_mirror<<endl;
cout<<"rb->read_mirror: "<<rb->read_mirror<<endl;
cout<<"rb_data_len: "<<rb_data_len(rb)<<endl;
cout<<"rb_space_len: "<<rb_space_len(rb)<<endl;
cout<<endl;
}
void writeprint(ringbuff* rb){
for(int i=0;i<rb->size;i++){
cout<<rb->buffer_ptr[i];
}
print(rb);
}
void test02() {
ringbuff* rb = rb_create(9);
cout<<"rb->size: "<<rb->size<<endl;
const uint8 p[] = "123456789ABCDEF";
uint32_t len = sizeof(p) / sizeof(char);
// cout<<len<<endl;
cout<<"寫(xiě)入數(shù)據(jù):"<<p<<endl;
for(int i=0;i<len-1;i++) {
// rb_putchar(rb,p[i]);
rb_putchar_force(rb,p[i]);
}
writeprint(rb); // 9ABCDEF8
uint8 singlechar = ' ';
for(int i=0;i<4;i++) {
rb_getchar(rb,&singlechar);
cout<<"讀單個(gè)字符: "<<singlechar<<endl;
}
print(rb);
// 銷(xiāo)毀ringbuff
rb_destroy(rb);
}
rb->size: 8
寫(xiě)入數(shù)據(jù):123456789ABCDEF
9ABCDEF8
rb->write_index: 7
rb->read_index: 7
rb->write_mirror: 1
rb->read_mirror: 0
rb_data_len: 8
rb_space_len: 0
讀單個(gè)字符: 8
讀單個(gè)字符: 9
讀單個(gè)字符: A
讀單個(gè)字符: B
rb->write_index: 7
rb->read_index: 3
rb->write_mirror: 1
rb->read_mirror: 1
rb_data_len: 4
rb_space_len: 4
銷(xiāo)毀ringbuff~
四、RT-Thread??小結(jié)
來(lái)自此文總結(jié):ring buffer,一篇文章講透它? - 知乎 (zhihu.com)
?? 在多線(xiàn)程中,對(duì)同一個(gè)環(huán)形緩沖區(qū)進(jìn)行讀寫(xiě)操作時(shí),需要加上鎖,不然存在訪(fǎng)問(wèn)不安全問(wèn)題;
?? 當(dāng)只有一個(gè)讀線(xiàn)程和一個(gè)寫(xiě)線(xiàn)程時(shí),用rb_put和rb_get進(jìn)行讀寫(xiě)操作緩沖區(qū)是線(xiàn)程安全的,無(wú)需加鎖;但是rb_put_force不行,因?yàn)槠淇赡軐?duì)讀寫(xiě)索引都進(jìn)行操作的場(chǎng)景,這個(gè)時(shí)候再進(jìn)行rb_get讀操作,就是不安全訪(fǎng)問(wèn);
?? 讀寫(xiě)指針已經(jīng)在讀寫(xiě)(rb_get和rb_put)過(guò)程中轉(zhuǎn)換為了讀寫(xiě)索引。所以read_index(讀索引)和write_index(寫(xiě)索引)可以直接用來(lái)操作緩沖區(qū),無(wú)需轉(zhuǎn)換;
?? read_index 和write_index 的大小區(qū)間為[0,n?1],n為緩沖區(qū)大?。?/p>
?? RT-Thread的環(huán)形緩沖區(qū)不需要buffer大小為2的冪。
五、完整代碼
rb.h
#ifndef RB
#define RB
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short wchar;
typedef unsigned short int uint16;
typedef signed short int int16;
typedef unsigned int uint32;
typedef signed int int32;
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
/*
* Return the down number of aligned at specified width. RT_ALIGN_DOWN(13, 4)
* would return 12.*/
#define DATA_ALIGN_DOWN(size, align) ((size) & ~((align) - 1))
/* DATA_ALIGN_SIZE*/
#define DATA_ALIGN_SIZE 4
/* ring buffer */
typedef struct ringbuffer
{
uint8 *buffer_ptr;
uint16 read_mirror : 1;
uint16 read_index : 15;
uint16 write_mirror : 1;
uint16 write_index : 15;
/* as we use msb of index as mirror bit, the size should be signed and
* could only be positive. */
uint16 size;
}ringbuff;
/* 緩沖區(qū)初始化 */
void rb_init(ringbuff *rb,uint8 *pool,uint16 size);
/* 創(chuàng)建一個(gè)ringbuff */
ringbuff* rb_create(uint16_t size);
/* 銷(xiāo)毀一個(gè)ringbuff */
void rb_destroy(ringbuff *rb);
/* 緩沖區(qū)中填充指定數(shù)據(jù)長(zhǎng)度的數(shù)據(jù)(當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事不覆蓋緩沖區(qū)原有數(shù)據(jù)) */
uint16 rb_put(ringbuff *rb,const uint8 *ptr,uint16 length);
/* 緩沖區(qū)中填充指定數(shù)據(jù)長(zhǎng)度的數(shù)據(jù)(當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事覆蓋緩沖區(qū)原有數(shù)據(jù)) */
uint16 rb_put_force(ringbuff *rb,const uint8 *ptr,uint16 length);
/* 緩沖區(qū)中填充一個(gè)數(shù)據(jù)(當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事不覆蓋緩沖區(qū)原有數(shù)據(jù)) */
uint16 rb_putchar(ringbuff *rb, const uint8 ch);
/* 緩沖區(qū)中填充一個(gè)數(shù)據(jù)(當(dāng)緩沖區(qū)空間小于待寫(xiě)入的數(shù)據(jù)長(zhǎng)度事覆蓋緩沖區(qū)原有數(shù)據(jù)) */
uint16 rb_putchar_force(ringbuff *rb, const uint8 ch);
/* 緩沖區(qū)中獲取指定長(zhǎng)度的數(shù)據(jù)(返回實(shí)際獲取數(shù)據(jù)的長(zhǎng)度) */
uint16 rb_get(ringbuff *rb,uint8 *ptr,uint16 length);
/* 緩沖區(qū)中獲取一個(gè)數(shù)據(jù)(返回實(shí)際獲取數(shù)據(jù)的長(zhǎng)度) */
uint16 rb_getchar(ringbuff *rb, uint8 *ch);
/* 獲取 ringbuff 中數(shù)據(jù)的長(zhǎng)度 */
uint16 rb_data_len(ringbuff *rb);
/** return the size of empty space in rb */
#define rb_space_len(rb) ((rb)->size - rb_data_len(rb))
#endif /* RB */
rb.cpp文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-660711.html
#include "rb.h"
enum rb_state
{
RINGBUFFER_EMPTY,
RINGBUFFER_FULL,
RINGBUFFER_HALFFULL, /* half full is neither full nor empty */
};
// 獲取 ringbuff 的狀態(tài)
enum rb_state rb_status(ringbuff *rb) {
if (rb->read_index == rb->write_index)
{
if (rb->read_mirror == rb->write_mirror)
return RINGBUFFER_EMPTY;
else
return RINGBUFFER_FULL;
}
return RINGBUFFER_HALFFULL;
}
// 獲取 ringbuff 中數(shù)據(jù)的長(zhǎng)度
uint16 rb_data_len(ringbuff *rb) {
switch (rb_status(rb)) {
case RINGBUFFER_EMPTY:
return 0;//空就返回 0
case RINGBUFFER_FULL:
return rb->size;// 滿(mǎn)就返回緩沖區(qū)的大小
case RINGBUFFER_HALFFULL:// 半滿(mǎn)
default:
if (rb->write_index > rb->read_index) // 如果在同一鏡像
return rb->write_index - rb->read_index; // 返回下標(biāo)差
else
return rb->size - (rb->read_index - rb->write_index); // 如果不在同一鏡像,通過(guò)計(jì)算獲取數(shù)據(jù)的長(zhǎng)度
};
}
// 緩沖區(qū)初始化
void rb_init(ringbuff *rb,uint8 *pool,uint16 size){
/* initialize read and write index */
rb->read_mirror = rb->read_index = 0;
rb->write_mirror = rb->write_index = 0;
/* set buffer pool and size */
rb->buffer_ptr = pool;
rb->size = DATA_ALIGN_DOWN(size, DATA_ALIGN_SIZE);
}
// 創(chuàng)建一個(gè)ringbuff
ringbuff* rb_create(uint16_t size) {
ringbuff *rb;
uint8_t *pool;
size = DATA_ALIGN_DOWN(size, DATA_ALIGN_SIZE);// 大小做字節(jié)對(duì)齊
rb = (ringbuff *)malloc(sizeof(ringbuff));// 申請(qǐng)內(nèi)存
if (rb == NULL)
goto exit;
pool = (uint8_t *)malloc(size);// 申請(qǐng)數(shù)據(jù)緩沖區(qū)內(nèi)存
if (pool == NULL) {
free(rb);
rb = NULL;
goto exit;
}
rb_init(rb, pool, size);// 初始化 ringbuff
exit:
return rb;
}
// 往 ringbuff 寫(xiě)入數(shù)據(jù)
uint16 rb_put(ringbuff *rb,const uint8 *ptr,uint16 length) {
uint16 size = 0;
/* whether has enough space */
size = rb_space_len(rb);// 獲取 ring_buff 中可用空間的大小
/* no space */
if (size == 0)
return 0;// 如果空間不夠 直接返回
/* drop some data */
if (size < length) // 如果緩存區(qū)的空間不夠保存這一次數(shù)據(jù), 則把能夠?qū)懭氲倪@一部分?jǐn)?shù)據(jù)寫(xiě)進(jìn)去
length = size;
/* One-time write */
if (rb->size - rb->write_index > length)
{
/* read_index - write_index = empty space */
memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
rb->write_index += length;
return length;// 返回寫(xiě)入數(shù)據(jù)的長(zhǎng)度
}
/* two-time write */
memcpy(&rb->buffer_ptr[rb->write_index],
&ptr[0],
rb->size - rb->write_index);
memcpy(&rb->buffer_ptr[0],
&ptr[rb->size - rb->write_index],
length - (rb->size - rb->write_index));
/* we are going into the other side of the mirror */
rb->write_mirror = ~rb->write_mirror;
rb->write_index = length - (rb->size - rb->write_index);
return length;
}
// 強(qiáng)制往 ringbuff 寫(xiě)入數(shù)據(jù)
uint16 rb_put_force(ringbuff *rb,const uint8 *ptr,uint16 length) {
uint16 space_length = 0;
space_length = rb_space_len(rb);
// cout<<"ptr: "<<ptr<<endl;
// cout<<"space_length: "<<space_length<<endl;
// cout<<"length: "<<length<<endl;
if (length > space_length) {
ptr = &ptr[length - rb->size];
length = rb->size;
}
// cout<<"ptr: "<<ptr<<endl;
// cout<<"length: "<<length<<endl;
if (rb->size - rb->write_index > length)
{
// cout<<"lailailailai"<<endl;
/* read_index - write_index = empty space */
memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
rb->write_index += length;
if (length > space_length)
rb->read_index = rb->write_index;
return length;
}
memcpy(&rb->buffer_ptr[rb->write_index],
&ptr[0],
rb->size - rb->write_index);
memcpy(&rb->buffer_ptr[0],
&ptr[rb->size - rb->write_index],
length - (rb->size - rb->write_index));
/* we are going into the other side of the mirror */
rb->write_mirror = ~rb->write_mirror;
rb->write_index = length - (rb->size - rb->write_index);
if (length > space_length)
{
rb->read_mirror = ~rb->read_mirror;
rb->read_index = rb->write_index;
}
return length;
}
// 從 ringbuff 獲取數(shù)據(jù)
uint16 rb_get(ringbuff *rb,uint8 *ptr,uint16 length) {
uint16 size = 0;
/* The length of the existing data in the buffer */
size = rb_data_len(rb);
/* no data */
if (size == 0)
return 0;
/* less data */
if (size < length)
length = size;
cout<<"size: "<<size<<" < "<<"length: " << length<<(size < length)<<endl;
if (rb->size - rb->read_index > length)
{
/* copy all of data */
memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
rb->read_index += length;
return length;
}
memcpy(&ptr[0],
&rb->buffer_ptr[rb->read_index],
rb->size - rb->read_index);
memcpy(&ptr[rb->size - rb->read_index],
&rb->buffer_ptr[0],
length - (rb->size - rb->read_index));
/* we are going into the other side of the mirror */
rb->read_mirror = ~rb->read_mirror;
rb->read_index = length - (rb->size - rb->read_index);
return length;
}
// 往 ringbuff 中寫(xiě)入一個(gè)字符
uint16 rb_putchar(ringbuff *rb, const uint8 ch) {
/* whether has enough space */
if (!rb_space_len(rb)) // 沒(méi)有足夠的空間就直接返回了
return 0;
rb->buffer_ptr[rb->write_index] = ch;// 把這個(gè)字符寫(xiě)入到緩沖區(qū)的指定位置
/* flip mirror */
if (rb->write_index == rb->size-1) {// 檢查寫(xiě)入這個(gè)字符后,當(dāng)前鏡像是否寫(xiě)滿(mǎn)
rb->write_mirror = ~rb->write_mirror;// 翻轉(zhuǎn)鏡像
rb->write_index = 0;// 設(shè)置下標(biāo)為0
}else{
rb->write_index++; // 下標(biāo)加1
}
return 1;// 寫(xiě)入一個(gè)字符,返回 1
}
// 往 ringbuff 強(qiáng)制寫(xiě)入一個(gè)字符
uint16 rb_putchar_force(ringbuff *rb, const uint8 ch) {
enum rb_state old_state = rb_status(rb);// 獲取狀態(tài)
rb->buffer_ptr[rb->write_index] = ch;// 寫(xiě)入數(shù)據(jù)
/* flip mirror */
if (rb->write_index == rb->size-1) {// 檢查當(dāng)前鏡像是不是滿(mǎn)了
rb->write_mirror = ~rb->write_mirror; // 翻轉(zhuǎn)寫(xiě)鏡像
rb->write_index = 0;// 翻轉(zhuǎn)之后設(shè)置下標(biāo)為 0
if (old_state == RINGBUFFER_FULL) {// 如果 ringbuff 的狀態(tài)是滿(mǎn)
rb->read_mirror = ~rb->read_mirror; // 翻轉(zhuǎn)讀鏡像
rb->read_index = rb->write_index; // 設(shè)置讀下標(biāo)和寫(xiě)下標(biāo)一致
}
}else{
rb->write_index++; // 寫(xiě)下標(biāo)加1
if (old_state == RINGBUFFER_FULL)
rb->read_index = rb->write_index;// 如果滿(mǎn),設(shè)置讀下標(biāo)等于寫(xiě)下標(biāo)
}
return 1; // 寫(xiě)入一個(gè)字符,返回1
}
// 從ringbuff 獲取一個(gè)字符
uint16 rb_getchar(ringbuff *rb,uint8 *ch) {
/* ringbuffer is empty */
if (!rb_data_len(rb)) // 檢查 ringbuff 是否為空
return 0;
/* put character */
*ch = rb->buffer_ptr[rb->read_index];// 獲取當(dāng)前讀下標(biāo)的數(shù)據(jù)
if (rb->read_index == rb->size-1) {// 如果當(dāng)前鏡像滿(mǎn)了
rb->read_mirror = ~rb->read_mirror;// 翻轉(zhuǎn)鏡像
rb->read_index = 0; // 設(shè)置讀數(shù)據(jù)的下標(biāo)為0
} else {
rb->read_index++; // 下標(biāo)加1
}
return 1;// 讀取一個(gè)字節(jié),返回1
}
// 摧毀 ringbuff
void rb_destroy(ringbuff *rb) {
cout<<"銷(xiāo)毀ringbuff~"<<endl;
free(rb->buffer_ptr);
free(rb);// 釋放申請(qǐng)的內(nèi)存
}
test.cpp文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-660711.html
#include "rb.h"
#include "rb.cpp"
void print(ringbuff *rb) {
cout<<endl;
cout<<"rb->write_index: "<<rb->write_index<<endl;
cout<<"rb->read_index: "<<rb->read_index<<endl;
cout<<"rb->write_mirror: "<<rb->write_mirror<<endl;
cout<<"rb->read_mirror: "<<rb->read_mirror<<endl;
cout<<"rb_data_len: "<<rb_data_len(rb)<<endl;
cout<<"rb_space_len: "<<rb_space_len(rb)<<endl;
cout<<endl;
}
void readprint(ringbuff* rb,uint8 buff[]) {
cout<<"讀取數(shù)據(jù):";
int i = 0;
while(buff[i]!='\0') {
cout<<buff[i++];
}
print(rb);
}
void writeprint(ringbuff* rb){
for(int i=0;i<rb->size;i++){
cout<<rb->buffer_ptr[i];
}
print(rb);
}
void test01() {
ringbuff* rb = rb_create(9);
const uint8 p[] = "123456789ABCDEF";
uint32_t len = sizeof(p) / sizeof(char);
cout<<"寫(xiě)入數(shù)據(jù):"<<p<<endl;
// rb_put(rb,p,len-1);
rb_put_force(rb,p,len-1);
writeprint(rb); // 89ABCDEF
uint8 saveBuff[20] = "";
rb_get(rb,saveBuff,4); // 89AB
readprint(rb,saveBuff);
const uint8 p1[] = "1234";
cout<<"寫(xiě)入數(shù)據(jù):"<<p1<<endl;
rb_put_force(rb,p1,4); // 1234CDEF
writeprint(rb);
memset(saveBuff,0,20);
rb_get(rb,saveBuff,4); // CDEF
cout<<"讀取數(shù)據(jù):";
readprint(rb,saveBuff);
// 銷(xiāo)毀ringbuff
rb_destroy(rb);
}
void test02() {
ringbuff* rb = rb_create(9);
cout<<"rb->size: "<<rb->size<<endl;
const uint8 p[] = "123456789ABCDEF";
uint32_t len = sizeof(p) / sizeof(char);
// cout<<len<<endl;
cout<<"寫(xiě)入數(shù)據(jù):"<<p<<endl;
for(int i=0;i<len-1;i++) {
// rb_putchar(rb,p[i]);
rb_putchar_force(rb,p[i]);
}
writeprint(rb); // 9ABCDEF8
uint8 singlechar = ' ';
for(int i=0;i<4;i++) {
rb_getchar(rb,&singlechar);
cout<<"讀單個(gè)字符: "<<singlechar<<endl;
}
print(rb);
// 銷(xiāo)毀ringbuff
rb_destroy(rb);
}
int main() {
// test01();
test02();
return 0;
}
到了這里,關(guān)于RT-Thread 的環(huán)形緩沖區(qū) ---- 鏡像指示位的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!