模仿kfifo实现的环形缓冲区
2018-01-16 22:15
417 查看
模仿kfifo实现的环形缓冲区
GitHub仓库:https://github.com/XinLiGitHub/RingBuffer
PS:博文不再更新,后续更新会在GitHub仓库进行。
模仿kfifo实现的环形缓冲区。程序中涉及到环形缓冲区的概念,详细介绍见维基百科[Circular buffer](https://en.wikipedia.org/wiki/Circular_buffer)。
1,开发环境
1,操作系统:Windows 10 专业版
2,IDE:Visual Studio 2015 专业版
2,程序源码
RingBuffer.h文件
RingBuffer.c文件
main.c文件
3,运行效果
GitHub仓库:https://github.com/XinLiGitHub/RingBuffer
PS:博文不再更新,后续更新会在GitHub仓库进行。
模仿kfifo实现的环形缓冲区。程序中涉及到环形缓冲区的概念,详细介绍见维基百科[Circular buffer](https://en.wikipedia.org/wiki/Circular_buffer)。
1,开发环境
1,操作系统:Windows 10 专业版
2,IDE:Visual Studio 2015 专业版
2,程序源码
RingBuffer.h文件
/** ****************************************************************************** * @file RingBuffer.h * @author XinLi * @version v1.0 * @date 15-January-2018 * @brief Header file for RingBuffer.c module. ****************************************************************************** * @attention * * <h2><center>Copyright © 2018 XinLi</center></h2> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. * ****************************************************************************** */ #ifndef __RINGBUFFER_H #define __RINGBUFFER_H #ifdef __cplusplus extern "C" { #endif /* Header includes -----------------------------------------------------------*/ #include <stdint.h> #include <stdbool.h> /* Macro definitions ---------------------------------------------------------*/ #define RING_BUFFER_MALLOC(size) malloc(size) #define RING_BUFFER_FREE(block) free(block) /* Type definitions ----------------------------------------------------------*/ typedef struct { uint8_t *buffer; uint32_t size; uint32_t in; uint32_t out; }RingBuffer; /* Variable declarations -----------------------------------------------------*/ /* Variable definitions ------------------------------------------------------*/ /* Function declarations -----------------------------------------------------*/ RingBuffer *RingBuffer_Malloc(uint32_t size); void RingBuffer_Free(RingBuffer *fifo); uint32_t RingBuffer_In(RingBuffer *fifo, void *in, uint32_t len); uint32_t RingBuffer_Out(RingBuffer *fifo, void *out, uint32_t len); /* Function definitions ------------------------------------------------------*/ /** * @brief Removes the entire FIFO contents. * @param [in] fifo: The fifo to be emptied. * @return None. */ static inline void RingBuffer_Reset(RingBuffer *fifo) { fifo->in = fifo->out = 0; } /** * @brief Returns the size of the FIFO in bytes. * @param [in] fifo: The fifo to be used. * @return The size of the FIFO. */ static inline uint32_t RingBuffer_Size(RingBuffer *fifo) { return fifo->size; } /** * @brief Returns the number of used bytes in the FIFO. * @param [in] fifo: The fifo to be used. * @return The number of used bytes. */ static inline uint32_t RingBuffer_Len(RingBuffer *fifo) { return fifo->in - fifo->out; } /** * @brief Returns the number of bytes available in the FIFO. * @param [in] fifo: The fifo to be used. * @return The number of bytes available. */ static inline uint32_t RingBuffer_Avail(RingBuffer *fifo) { return RingBuffer_Size(fifo) - RingBuffer_Len(fifo); } /** * @brief Is the FIFO empty? * @param [in] fifo: The fifo to be used. * @retval true: Yes. * @retval false: No. */ static inline bool RingBuffer_IsEmpty(RingBuffer *fifo) { return RingBuffer_Len(fifo) == 0; } /** * @brief Is the FIFO full? * @param [in] fifo: The fifo to be used. * @retval true: Yes. * @retval false: No. */ static inline bool RingBuffer_IsFull(RingBuffer *fifo) { return RingBuffer_Avail(fifo) == 0; } #ifdef __cplusplus } #endif #endif /* __RINGBUFFER_H */
RingBuffer.c文件
/** ****************************************************************************** * @file RingBuffer.c * @author XinLi * @version v1.0 * @date 15-January-2018 * @brief Ring buffer module source file. ****************************************************************************** * @attention * * <h2><center>Copyright © 2018 XinLi</center></h2> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. * ****************************************************************************** */ /* Header includes -----------------------------------------------------------*/ #include "RingBuffer.h" #include <stdlib.h> #include <string.h> /* Macro definitions ---------------------------------------------------------*/ /* Type definitions ----------------------------------------------------------*/ /* Variable declarations -----------------------------------------------------*/ /* Variable definitions ------------------------------------------------------*/ /* Function declarations -----------------------------------------------------*/ static bool is_power_of_2(uint32_t x); static uint32_t roundup_pow_of_two(uint32_t x); /* Function definitions ------------------------------------------------------*/ /** * @brief Allocates a new FIFO and its internal buffer. * @param [in] size: The size of the internal buffer to be allocated. * @note The size will be rounded-up to a power of 2. * @return RingBuffer pointer. */ RingBuffer *RingBuffer_Malloc(uint32_t size) { RingBuffer *fifo = RING_BUFFER_MALLOC(sizeof(RingBuffer)); if(fifo != NULL) { if(is_power_of_2(size) != true) { if(size > 0x80000000UL) { RING_BUFFER_FREE(fifo); fifo = NULL; return fifo; } size = roundup_pow_of_two(size); } fifo->size = size; fifo->in = 0; fifo->out = 0; fifo->buffer = RING_BUFFER_MALLOC(fifo->size); if(fifo->buffer == NULL) { RING_BUFFER_FREE(fifo); fifo = NULL; return fifo; } } return fifo; } /** * @brief Frees the FIFO. * @param [in] fifo: The fifo to be freed. * @return None. */ void RingBuffer_Free(RingBuffer *fifo) { RING_BUFFER_FREE(fifo->buffer); RING_BUFFER_FREE(fifo); fifo = NULL; } /** * @brief Puts some data into the FIFO. * @param [in] fifo: The fifo to be used. * @param [in] in: The data to be added. * @param [in] len: The length of the data to be added. * @return The number of bytes copied. * @note This function copies at most @len bytes from the @in into * the FIFO depending on the free space, and returns the number * of bytes copied. */ uint32_t RingBuffer_In(RingBuffer *fifo, void *in, uint32_t len) { len = min(len, RingBuffer_Avail(fifo)); /* First put the data starting from fifo->in to buffer end. */ uint32_t l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), in, l); /* Then put the rest (if any) at the beginning of the buffer. */ memcpy(fifo->buffer, (uint8_t *)in + l, len - l); fifo->in += len; return len; } /** * @brief Gets some data from the FIFO. * @param [in] fifo: The fifo to be used. * @param [in] out: Where the data must be copied. * @param [in] len: The size of the destination buffer. * @return The number of copied bytes. * @note This function copies at most @len bytes from the FIFO into * the @out and returns the number of copied bytes. */ uint32_t RingBuffer_Out(RingBuffer *fifo, void *out, uint32_t len) { len = min(len, RingBuffer_Len(fifo)); /* First get the data from fifo->out until the end of the buffer. */ uint32_t l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); memcpy(out, fifo->buffer + (fifo->out & (fifo->size - 1)), l); /* Then get the rest (if any) from the beginning of the buffer. */ memcpy((uint8_t *)out + l, fifo->buffer, len - l); fifo-> d74c ;out += len; return len; } /** * @brief Determine whether some value is a power of two. * @param [in] x: The number to be confirmed. * @retval true: Yes. * @retval false: No. * @note Where zero is not considered a power of two. */ static bool is_power_of_2(uint32_t x) { return (x != 0) && ((x & (x - 1)) == 0); } /** * @brief Round the given value up to nearest power of two. * @param [in] x: The number to be converted. * @return The power of two. */ static uint32_t roundup_pow_of_two(uint32_t x) { uint32_t b = 0; for(int i = 0; i < 32; i++) { b = 1UL << i; if(x <= b) { break; } } return b; }
main.c文件
/** ****************************************************************************** * @file main.c * @author XinLi * @version v1.0 * @date 15-January-2018 * @brief Main program body. ****************************************************************************** * @attention * * <h2><center>Copyright © 2018 XinLi</center></h2> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. * ****************************************************************************** */ /* Header includes -----------------------------------------------------------*/ #include "RingBuffer.h" #include <stdio.h> #include <windows.h> /* Macro definitions ---------------------------------------------------------*/ /* Type definitions ----------------------------------------------------------*/ /* Variable declarations -----------------------------------------------------*/ /* Variable definitions ------------------------------------------------------*/ /* Function declarations -----------------------------------------------------*/ /* Function definitions ------------------------------------------------------*/ /** * @brief Main program. * @param None. * @return None. */ int main(void) { uint8_t data[256] = {0}; for(int i = 0; i < sizeof(data); i++) { data[i] = i; } RingBuffer *fifo = RingBuffer_Malloc(sizeof(data)); if(fifo != NULL) { printf("FIFO创建成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); if(RingBuffer_IsFull(fifo) == true) { printf("FIFO满了!!!\n"); } else { printf("FIFO没满!!!\n"); } if(RingBuffer_IsEmpty(fifo) == true) { printf("FIFO空了!!!\n"); } else { printf("FIFO没空!!!\n"); } printf("\n"); for(;;) { { if(RingBuffer_In(fifo, data, sizeof(data) / 2) > 0) { printf("FIFO写入成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } else { printf("FIFO写入失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } if(RingBuffer_IsFull(fifo) == true) { printf("FIFO满了!!!\n"); } else { printf("FIFO没满!!!\n"); } if(RingBuffer_IsEmpty(fifo) == true) { printf("FIFO空了!!!\n"); } else { printf("FIFO没空!!!\n"); } } printf("\n"); { uint8_t rdata[64] = {0}; uint8_t len = RingBuffer_Out(fifo, rdata, sizeof(rdata)); if(len > 0) { printf("从FIFO中读出的数据,长度:%d\n", len); for(int i = 0; i < len; i++) { printf("%d ", rdata[i]); } printf("\n"); printf("FIFO读取成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } else { printf("FIFO读取失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } if(RingBuffer_IsFull(fifo) == true) { printf("FIFO满了!!!\n"); } else { printf("FIFO没满!!!\n"); } if(RingBuffer_IsEmpty(fifo) == true) { printf("FIFO空了!!!\n"); } else { printf("FIFO没空!!!\n"); } } printf("\n"); { RingBuffer_Reset(fifo); printf("FIFO清空成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); if(RingBuffer_IsFull(fifo) == true) { printf("FIFO满了!!!\n"); } else { printf("FIFO没满!!!\n"); } if(RingBuffer_IsEmpty(fifo) == true) { printf("FIFO空了!!!\n"); } else { printf("FIFO没空!!!\n"); } } printf("\n"); { if(RingBuffer_In(fifo, data, sizeof(data)) > 0) { printf("FIFO写入成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } else { printf("FIFO写入失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } if(RingBuffer_IsFull(fifo) == true) { printf("FIFO满了!!!\n"); } else { printf("FIFO没满!!!\n"); } if(RingBuffer_IsEmpty(fifo) == true) { printf("FIFO空了!!!\n"); } else { printf("FIFO没空!!!\n"); } } printf("\n"); { if(RingBuffer_In(fifo, data, sizeof(data)) > 0) { printf("FIFO写入成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } else { printf("FIFO写入失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } if(RingBuffer_IsFull(fifo) == true) { printf("FIFO满了!!!\n"); } else { printf("FIFO没满!!!\n"); } if(RingBuffer_IsEmpty(fifo) == true) { printf("FIFO空了!!!\n"); } else { printf("FIFO没空!!!\n"); } } printf("\n"); { uint8_t rdata[256] = {0}; uint16_t len = RingBuffer_Out(fifo, rdata, sizeof(rdata)); if(len > 0) { printf("从FIFO中读出的数据,长度:%d\n", len); for(int i = 0; i < len; i++) { printf("%d ", rdata[i]); } printf("\n"); printf("FIFO读取成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } else { printf("FIFO读取失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } if(RingBuffer_IsFull(fifo) == true) { printf("FIFO满了!!!\n"); } else { printf("FIFO没满!!!\n"); } if(RingBuffer_IsEmpty(fifo) == true) { printf("FIFO空了!!!\n"); } else { printf("FIFO没空!!!\n"); } } printf("\n"); { uint8_t rdata[256] = {0}; uint16_t len = RingBuffer_Out(fifo, rdata, sizeof(rdata)); if(len > 0) { printf("从FIFO中读出的数据,长度:%d\n", len); for(int i = 0; i < len; i++) { printf("%d ", rdata[i]); } printf("\n"); printf("FIFO读取成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } else { printf("FIFO读取失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n", RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo)); } if(RingBuffer_IsFull(fifo) == true) { printf("FIFO满了!!!\n"); } else { printf("FIFO没满!!!\n"); } if(RingBuffer_IsEmpty(fifo) == true) { printf("FIFO空了!!!\n"); } else { printf("FIFO没空!!!\n"); } } printf("\n\n\n"); Sleep(5000); } } else { printf("FIFO创建失败\n"); } for(;;) { } }
3,运行效果
相关文章推荐
- 读Linux内核(4.9.9)之环形缓冲区实现kfifo
- 环形缓冲区-模仿linux kfifo
- (转载)环形缓冲区的实现原理(ring buffer)
- linux 管道的环形buffer(缓冲区) 实现原理
- C# 中实现 FIFO 缓冲区–ArrayBuffer(环形缓冲区)
- 架构设计:生产者/消费者模式 第6页:环形缓冲区的实现
- 环形缓冲区的实现原理(ring buffer)
- 环形缓冲区的C语言实现
- 环形缓冲区的实现原理
- C++ 无锁环形缓冲区实现
- 51内核UART串行总线环形缓冲区驱动实现
- 一个免锁环形缓冲区的实现
- 服务器公共组件实现 -- 环形缓冲区
- 环形缓冲区的实现原理(ring buffer)
- 嵌入式 环形缓冲区的设计与实现
- 环形缓冲区的实现
- stm32F4 串口DMA+环形缓冲区的实现
- 服务器公共组件实现 -- 环形缓冲区
- 一个简单的环形缓冲区的实现
- C++ 环形缓冲区的实现