环形缓冲区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

 

posted on 2023-11-30 09:44  凡仕  阅读(200)  评论(0编辑  收藏  举报