环形缓冲区FIFO
-------------------------------------------------------------------------------------------------------------------------------------
最近学习一个LwRB开源环形缓冲区FIFO设计,即先入先出缓冲区。LwRB 是一个开源、通用环形缓冲区库。
1、只有单个任务写和单个任务读时,线程是安全的
2、只有单个中断写和单个中断读时,中断是安全的
3、支持内存间的 DMA 操作,实现缓冲区和应用程序内存之间零拷贝
4、对于读数据,提供 peek(窥读,读数据但不改变读指针) 、skip (跳读,向前移动读指针,将指定长度的数据标记为已读)函数,
5、对于写数据,提供 advance (跳写,向前移动写指针,比如 DMA 硬件向环形缓冲区写入了 10 字节,应用程序需要调用此函数更新写指针)函数。
6、支持事件通知
具体的设计思路和原理图,可以观看这篇转载的博客:https://blog.csdn.net/zhzht19861011/article/details/126524101?spm=1001.2014.3001.5506
这里通过一些程序,简单介绍这个环形缓冲区的具体使用过程:
// 写入数据到循环缓冲区 size_t writeBytes = lwrb_write(&KEY_buff, "0123456789", 10); //向循环缓冲区 KEY_buff 写入字符串 “0123456789” 数据 printf("写入数据大小:%d\r\n", (int)writeBytes); // 获取缓冲区中已存储的数据大小 size_t full_data = lwrb_get_full(&KEY_buff); printf("已存储数据大小: %d\r\n", (int)full_data); //打印已经存储缓冲区中的大小 //lwrb_read 函数读取数据后会移动读指针,也就是读取数据后,环形缓冲区会将这些数据移除掉 uint8_t readData[BUFFER_SIZE]; size_t readBytes = lwrb_read(&KEY_buff, readData, 5); //从缓冲区中读取的字节数为5 printf("读取数据大小:%d\r\n", (int)readBytes); printf("read_data: "); for (int i = 0; i < readBytes; i++) { printf("%c", readData[i]); //打印读出的数据 } printf("\n"); // lwrb_peek() 函数用于查看循环缓冲区 KEY_buff 中的数据,不改变缓冲区中的数据位置 uint8_t peekData[BUFFER_SIZE]; size_t peekBytes = lwrb_peek(&KEY_buff, 2, peekData, BUFFER_SIZE); //在BUFFER_SIZE缓冲区中从索引2开始查看 printf("查看数据大小:%d\r\n", (int)peekBytes); printf("Peek_data: "); for (int i = 0; i < peekBytes; i++) { printf("%c", peekData[i]); } printf("\n"); //lwrb_skip() 函数用于跳过循环缓冲区 KEY_buff 中的数据 size_t skipBytes = lwrb_skip(&KEY_buff, 4); // 跳过 4 个字节 printf("跳过数据data:%d\r\n", (int)skipBytes); // 获取缓冲区中已存储的数据大小 full_data = lwrb_get_full(&KEY_buff); printf("再一次已存储数据大小: %d\r\n", (int)full_data); // 再次读取数据 size_t readBytes2 = lwrb_read(&KEY_buff, readData, BUFFER_SIZE); printf("再一次读取数据大小:%d\r\n", (int)readBytes2); printf("data2: "); for (int i = 0; i < readBytes2; i++) { printf("%c", readData[i]); //打印读出缓冲区中跳过4个字节后的数据 } printf("\n");
通过串口打印出数据
在程序中,
1、通过lwrb_write函数向环形缓冲区写数据,数据将“0123456789”指向的数组拷贝到环形缓冲区,
2、通过lwrb_get_full函数获取当前缓冲区中已存储的数据大小
3、通过lwrb_read函数将数据从环形缓冲区拷贝到指向的数组readData里面,读取数据后会移动读指针,也就是读取数据后,环形缓冲区会将这些数据移除掉。将读取的数据和数据个数打印出来,即01234。
4、通过lwrb_peek() 函数用于查看循环缓冲区 KEY_buff 中的数据,不改变缓冲区中的数据位置。程序中在缓冲区中从索引2开始查看,也就是56789这五个数据第三个数据开始查看。此时,打印出来的数据时789。
lwrb_peek 函数不移动读指针,也就是读取数据后,环形缓冲区不会将这些数据移除掉,就只是到环形缓冲区中看看这些数据都是什么样子,并不把数据拿出来,也就称为窥读。
相比 lwrb_read 函数,lwrb_peek 函数多了一个参数。这个参数是允许用户先跳过指定的字节数,再开始读取。
5、通过lwrb_skip() 函数用于跳过循环缓冲区 KEY_buff 中的数据,数据并不会被保存到用户层,而是直接丢弃掉,就是环形缓冲区会删除这些数据,就像跳过了这些数据,所以称为跳读。
在程序中,写了跳过4个数据,也就是将56789五个数据,跳过前面四个数据,也就是将5678这四个数据删掉。
6、通过lwrb_get_full函数和lwrb_read函数,读取此时的缓冲区中的数据,通过打印可以看出只有一个数据,就是最后一个9。
这篇有关的环形缓冲区学习都是来自于以下博客,可自行查看原文
【转载】:https://blog.csdn.net/zhzht19861011/article/details/126524101?spm=1001.2014.3001.5506