硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2386|回复: 1
收起左侧

模仿kfifo实现的环形缓冲区

[复制链接]

19

主题

15

回帖

72

积分

初级会员

积分
72
发表于 2018-2-1 23:52:34 | 显示全部楼层 |阅读模式
模仿kfifo实现的环形缓冲区


转载来源:模仿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文件

  1. /**
  2.   ******************************************************************************
  3.   * @file    RingBuffer.h
  4.   * @author  XinLi
  5.   * @version v1.0
  6.   * @date    15-January-2018
  7.   * @brief   Header file for RingBuffer.c module.
  8.   ******************************************************************************
  9.   * @attention
  10.   *
  11.   * <h2><center>Copyright &#169; 2018 XinLi</center></h2>
  12.   *
  13.   * This program is free software: you can redistribute it and/or modify
  14.   * it under the terms of the GNU General Public License as published by
  15.   * the Free Software Foundation, either version 3 of the License, or
  16.   * (at your option) any later version.
  17.   *
  18.   * This program is distributed in the hope that it will be useful,
  19.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.   * GNU General Public License for more details.
  22.   *
  23.   * You should have received a copy of the GNU General Public License
  24.   * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  25.   *
  26.   ******************************************************************************
  27.   */

  28. #ifndef __RINGBUFFER_H
  29. #define __RINGBUFFER_H

  30. #ifdef __cplusplus
  31. extern "C" {
  32. #endif

  33. /* Header includes -----------------------------------------------------------*/
  34. #include <stdint.h>
  35. #include <stdbool.h>

  36. /* Macro definitions ---------------------------------------------------------*/
  37. #define RING_BUFFER_MALLOC(size)  malloc(size)
  38. #define RING_BUFFER_FREE(block)   free(block)

  39. /* Type definitions ----------------------------------------------------------*/
  40. typedef struct
  41. {
  42.   uint8_t *buffer;
  43.   uint32_t size;
  44.   uint32_t in;
  45.   uint32_t out;
  46. }RingBuffer;

  47. /* Variable declarations -----------------------------------------------------*/
  48. /* Variable definitions ------------------------------------------------------*/
  49. /* Function declarations -----------------------------------------------------*/
  50. RingBuffer *RingBuffer_Malloc(uint32_t size);
  51. void RingBuffer_Free(RingBuffer *fifo);
  52. uint32_t RingBuffer_In(RingBuffer *fifo, void *in, uint32_t len);
  53. uint32_t RingBuffer_Out(RingBuffer *fifo, void *out, uint32_t len);

  54. /* Function definitions ------------------------------------------------------*/

  55. /**
  56.   * @brief  Removes the entire FIFO contents.
  57.   * @param  [in] fifo: The fifo to be emptied.
  58.   * @return None.
  59.   */
  60. static inline void RingBuffer_Reset(RingBuffer *fifo)
  61. {
  62.   fifo->in = fifo->out = 0;
  63. }

  64. /**
  65.   * @brief  Returns the size of the FIFO in bytes.
  66.   * @param  [in] fifo: The fifo to be used.
  67.   * @return The size of the FIFO.
  68.   */
  69. static inline uint32_t RingBuffer_Size(RingBuffer *fifo)
  70. {
  71.   return fifo->size;
  72. }

  73. /**
  74.   * @brief  Returns the number of used bytes in the FIFO.
  75.   * @param  [in] fifo: The fifo to be used.
  76.   * @return The number of used bytes.
  77.   */
  78. static inline uint32_t RingBuffer_Len(RingBuffer *fifo)
  79. {
  80.   return fifo->in - fifo->out;
  81. }

  82. /**
  83.   * @brief  Returns the number of bytes available in the FIFO.
  84.   * @param  [in] fifo: The fifo to be used.
  85.   * @return The number of bytes available.
  86.   */
  87. static inline uint32_t RingBuffer_Avail(RingBuffer *fifo)
  88. {
  89.   return RingBuffer_Size(fifo) - RingBuffer_Len(fifo);
  90. }

  91. /**
  92.   * @brief  Is the FIFO empty?
  93.   * @param  [in] fifo: The fifo to be used.
  94.   * @retval true:      Yes.
  95.   * @retval false:     No.
  96.   */
  97. static inline bool RingBuffer_IsEmpty(RingBuffer *fifo)
  98. {
  99.   return RingBuffer_Len(fifo) == 0;
  100. }

  101. /**
  102.   * @brief  Is the FIFO full?
  103.   * @param  [in] fifo: The fifo to be used.
  104.   * @retval true:      Yes.
  105.   * @retval false:     No.
  106.   */
  107. static inline bool RingBuffer_IsFull(RingBuffer *fifo)
  108. {
  109.   return RingBuffer_Avail(fifo) == 0;
  110. }

  111. #ifdef __cplusplus
  112. }
  113. #endif

  114. #endif /* __RINGBUFFER_H */
复制代码

      RingBuffer.c文件
  1. /**
  2.   ******************************************************************************
  3.   * @file    RingBuffer.c
  4.   * @author  XinLi
  5.   * @version v1.0
  6.   * @date    15-January-2018
  7.   * @brief   Ring buffer module source file.
  8.   ******************************************************************************
  9.   * @attention
  10.   *
  11.   * <h2><center>Copyright &#169; 2018 XinLi</center></h2>
  12.   *
  13.   * This program is free software: you can redistribute it and/or modify
  14.   * it under the terms of the GNU General Public License as published by
  15.   * the Free Software Foundation, either version 3 of the License, or
  16.   * (at your option) any later version.
  17.   *
  18.   * This program is distributed in the hope that it will be useful,
  19.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.   * GNU General Public License for more details.
  22.   *
  23.   * You should have received a copy of the GNU General Public License
  24.   * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  25.   *
  26.   ******************************************************************************
  27.   */

  28. /* Header includes -----------------------------------------------------------*/
  29. #include "RingBuffer.h"
  30. #include <stdlib.h>
  31. #include <string.h>

  32. /* Macro definitions ---------------------------------------------------------*/
  33. /* Type definitions ----------------------------------------------------------*/
  34. /* Variable declarations -----------------------------------------------------*/
  35. /* Variable definitions ------------------------------------------------------*/
  36. /* Function declarations -----------------------------------------------------*/
  37. static bool is_power_of_2(uint32_t x);
  38. static uint32_t roundup_pow_of_two(uint32_t x);

  39. /* Function definitions ------------------------------------------------------*/

  40. /**
  41.   * @brief  Allocates a new FIFO and its internal buffer.
  42.   * @param  [in] size: The size of the internal buffer to be allocated.
  43.   * @note   The size will be rounded-up to a power of 2.
  44.   * @return RingBuffer pointer.
  45.   */
  46. RingBuffer *RingBuffer_Malloc(uint32_t size)
  47. {
  48.   RingBuffer *fifo = RING_BUFFER_MALLOC(sizeof(RingBuffer));

  49.   if(fifo != NULL)
  50.   {
  51.     if(is_power_of_2(size) != true)
  52.     {
  53.       if(size > 0x80000000UL)
  54.       {
  55.         RING_BUFFER_FREE(fifo);
  56.         fifo = NULL;
  57.         return fifo;
  58.       }

  59.       size = roundup_pow_of_two(size);
  60.     }

  61.     fifo->size   = size;
  62.     fifo->in     = 0;
  63.     fifo->out    = 0;
  64.     fifo->buffer = RING_BUFFER_MALLOC(fifo->size);

  65.     if(fifo->buffer == NULL)
  66.     {
  67.       RING_BUFFER_FREE(fifo);
  68.       fifo = NULL;
  69.       return fifo;
  70.     }
  71.   }

  72.   return fifo;
  73. }

  74. /**
  75.   * @brief  Frees the FIFO.
  76.   * @param  [in] fifo: The fifo to be freed.
  77.   * @return None.
  78.   */
  79. void RingBuffer_Free(RingBuffer *fifo)
  80. {
  81.   RING_BUFFER_FREE(fifo->buffer);
  82.   RING_BUFFER_FREE(fifo);
  83.   fifo = NULL;
  84. }

  85. /**
  86.   * @brief  Puts some data into the FIFO.
  87.   * @param  [in] fifo: The fifo to be used.
  88.   * @param  [in] in:   The data to be added.
  89.   * @param  [in] len:  The length of the data to be added.
  90.   * @return The number of bytes copied.
  91.   * @note   This function copies at most @len bytes from the @in into
  92.   *         the FIFO depending on the free space, and returns the number
  93.   *         of bytes copied.
  94.   */
  95. uint32_t RingBuffer_In(RingBuffer *fifo, void *in, uint32_t len)
  96. {
  97.   len = min(len, RingBuffer_Avail(fifo));

  98.   /* First put the data starting from fifo->in to buffer end. */
  99.   uint32_t l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
  100.   memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), in, l);

  101.   /* Then put the rest (if any) at the beginning of the buffer. */
  102.   memcpy(fifo->buffer, (uint8_t *)in + l, len - l);

  103.   fifo->in += len;

  104.   return len;
  105. }

  106. /**
  107.   * @brief  Gets some data from the FIFO.
  108.   * @param  [in] fifo: The fifo to be used.
  109.   * @param  [in] out:  Where the data must be copied.
  110.   * @param  [in] len:  The size of the destination buffer.
  111.   * @return The number of copied bytes.
  112.   * @note   This function copies at most @len bytes from the FIFO into
  113.   *         the @out and returns the number of copied bytes.
  114.   */
  115. uint32_t RingBuffer_Out(RingBuffer *fifo, void *out, uint32_t len)
  116. {
  117.   len = min(len, RingBuffer_Len(fifo));

  118.   /* First get the data from fifo->out until the end of the buffer. */
  119.   uint32_t l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
  120.   memcpy(out, fifo->buffer + (fifo->out & (fifo->size - 1)), l);

  121.   /* Then get the rest (if any) from the beginning of the buffer. */
  122.   memcpy((uint8_t *)out + l, fifo->buffer, len - l);

  123.   fifo->out += len;

  124.   return len;
  125. }

  126. /**
  127.   * @brief  Determine whether some value is a power of two.
  128.   * @param  [in] x: The number to be confirmed.
  129.   * @retval true:   Yes.
  130.   * @retval false:  No.
  131.   * @note   Where zero is not considered a power of two.
  132.   */
  133. static bool is_power_of_2(uint32_t x)
  134. {
  135.   return (x != 0) && ((x & (x - 1)) == 0);
  136. }

  137. /**
  138.   * @brief  Round the given value up to nearest power of two.
  139.   * @param  [in] x: The number to be converted.
  140.   * @return The power of two.
  141.   */
  142. static uint32_t roundup_pow_of_two(uint32_t x)
  143. {
  144.   uint32_t b = 0;

  145.   for(int i = 0; i < 32; i++)
  146.   {
  147.     b = 1UL << i;

  148.     if(x <= b)
  149.     {
  150.       break;
  151.     }
  152.   }

  153.   return b;
  154. }
复制代码

      main.c文件
  1. /**
  2.   ******************************************************************************
  3.   * @file    main.c
  4.   * @author  XinLi
  5.   * @version v1.0
  6.   * @date    15-January-2018
  7.   * @brief   Main program body.
  8.   ******************************************************************************
  9.   * @attention
  10.   *
  11.   * <h2><center>Copyright &#169; 2018 XinLi</center></h2>
  12.   *
  13.   * This program is free software: you can redistribute it and/or modify
  14.   * it under the terms of the GNU General Public License as published by
  15.   * the Free Software Foundation, either version 3 of the License, or
  16.   * (at your option) any later version.
  17.   *
  18.   * This program is distributed in the hope that it will be useful,
  19.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.   * GNU General Public License for more details.
  22.   *
  23.   * You should have received a copy of the GNU General Public License
  24.   * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  25.   *
  26.   ******************************************************************************
  27.   */

  28. /* Header includes -----------------------------------------------------------*/
  29. #include "RingBuffer.h"
  30. #include <stdio.h>
  31. #include <windows.h>

  32. /* Macro definitions ---------------------------------------------------------*/
  33. /* Type definitions ----------------------------------------------------------*/
  34. /* Variable declarations -----------------------------------------------------*/
  35. /* Variable definitions ------------------------------------------------------*/
  36. /* Function declarations -----------------------------------------------------*/
  37. /* Function definitions ------------------------------------------------------*/

  38. /**
  39.   * @brief  Main program.
  40.   * @param  None.
  41.   * @return None.
  42.   */
  43. int main(void)
  44. {
  45.   uint8_t data[256] = {0};

  46.   for(int i = 0; i < sizeof(data); i++)
  47.   {
  48.     data[i] = i;
  49.   }

  50.   RingBuffer *fifo = RingBuffer_Malloc(sizeof(data));

  51.   if(fifo != NULL)
  52.   {
  53.     printf("FIFO创建成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  54.            RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));

  55.     if(RingBuffer_IsFull(fifo) == true)
  56.     {
  57.       printf("FIFO满了!!!\n");
  58.     }
  59.     else
  60.     {
  61.       printf("FIFO没满!!!\n");
  62.     }

  63.     if(RingBuffer_IsEmpty(fifo) == true)
  64.     {
  65.       printf("FIFO空了!!!\n");
  66.     }
  67.     else
  68.     {
  69.       printf("FIFO没空!!!\n");
  70.     }

  71.     printf("\n");

  72.     for(;;)
  73.     {
  74.       {
  75.         if(RingBuffer_In(fifo, data, sizeof(data) / 2) > 0)
  76.         {
  77.           printf("FIFO写入成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  78.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  79.         }
  80.         else
  81.         {
  82.           printf("FIFO写入失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  83.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  84.         }

  85.         if(RingBuffer_IsFull(fifo) == true)
  86.         {
  87.           printf("FIFO满了!!!\n");
  88.         }
  89.         else
  90.         {
  91.           printf("FIFO没满!!!\n");
  92.         }

  93.         if(RingBuffer_IsEmpty(fifo) == true)
  94.         {
  95.           printf("FIFO空了!!!\n");
  96.         }
  97.         else
  98.         {
  99.           printf("FIFO没空!!!\n");
  100.         }
  101.       }

  102.       printf("\n");

  103.       {
  104.         uint8_t rdata[64] = {0};
  105.         uint8_t len       = RingBuffer_Out(fifo, rdata, sizeof(rdata));

  106.         if(len > 0)
  107.         {
  108.           printf("从FIFO中读出的数据,长度:%d\n", len);

  109.           for(int i = 0; i < len; i++)
  110.           {
  111.             printf("%d ", rdata[i]);
  112.           }

  113.           printf("\n");

  114.           printf("FIFO读取成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  115.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  116.         }
  117.         else
  118.         {
  119.           printf("FIFO读取失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  120.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  121.         }

  122.         if(RingBuffer_IsFull(fifo) == true)
  123.         {
  124.           printf("FIFO满了!!!\n");
  125.         }
  126.         else
  127.         {
  128.           printf("FIFO没满!!!\n");
  129.         }

  130.         if(RingBuffer_IsEmpty(fifo) == true)
  131.         {
  132.           printf("FIFO空了!!!\n");
  133.         }
  134.         else
  135.         {
  136.           printf("FIFO没空!!!\n");
  137.         }
  138.       }

  139.       printf("\n");

  140.       {
  141.         RingBuffer_Reset(fifo);
  142.         printf("FIFO清空成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  143.                RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));

  144.         if(RingBuffer_IsFull(fifo) == true)
  145.         {
  146.           printf("FIFO满了!!!\n");
  147.         }
  148.         else
  149.         {
  150.           printf("FIFO没满!!!\n");
  151.         }

  152.         if(RingBuffer_IsEmpty(fifo) == true)
  153.         {
  154.           printf("FIFO空了!!!\n");
  155.         }
  156.         else
  157.         {
  158.           printf("FIFO没空!!!\n");
  159.         }
  160.       }

  161.       printf("\n");

  162.       {
  163.         if(RingBuffer_In(fifo, data, sizeof(data)) > 0)
  164.         {
  165.           printf("FIFO写入成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  166.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  167.         }
  168.         else
  169.         {
  170.           printf("FIFO写入失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  171.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  172.         }

  173.         if(RingBuffer_IsFull(fifo) == true)
  174.         {
  175.           printf("FIFO满了!!!\n");
  176.         }
  177.         else
  178.         {
  179.           printf("FIFO没满!!!\n");
  180.         }

  181.         if(RingBuffer_IsEmpty(fifo) == true)
  182.         {
  183.           printf("FIFO空了!!!\n");
  184.         }
  185.         else
  186.         {
  187.           printf("FIFO没空!!!\n");
  188.         }
  189.       }

  190.       printf("\n");

  191.       {
  192.         if(RingBuffer_In(fifo, data, sizeof(data)) > 0)
  193.         {
  194.           printf("FIFO写入成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  195.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  196.         }
  197.         else
  198.         {
  199.           printf("FIFO写入失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  200.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  201.         }

  202.         if(RingBuffer_IsFull(fifo) == true)
  203.         {
  204.           printf("FIFO满了!!!\n");
  205.         }
  206.         else
  207.         {
  208.           printf("FIFO没满!!!\n");
  209.         }

  210.         if(RingBuffer_IsEmpty(fifo) == true)
  211.         {
  212.           printf("FIFO空了!!!\n");
  213.         }
  214.         else
  215.         {
  216.           printf("FIFO没空!!!\n");
  217.         }
  218.       }

  219.       printf("\n");

  220.       {
  221.         uint8_t  rdata[256] = {0};
  222.         uint16_t len        = RingBuffer_Out(fifo, rdata, sizeof(rdata));

  223.         if(len > 0)
  224.         {
  225.           printf("从FIFO中读出的数据,长度:%d\n", len);

  226.           for(int i = 0; i < len; i++)
  227.           {
  228.             printf("%d ", rdata[i]);
  229.           }

  230.           printf("\n");

  231.           printf("FIFO读取成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  232.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  233.         }
  234.         else
  235.         {
  236.           printf("FIFO读取失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  237.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  238.         }

  239.         if(RingBuffer_IsFull(fifo) == true)
  240.         {
  241.           printf("FIFO满了!!!\n");
  242.         }
  243.         else
  244.         {
  245.           printf("FIFO没满!!!\n");
  246.         }

  247.         if(RingBuffer_IsEmpty(fifo) == true)
  248.         {
  249.           printf("FIFO空了!!!\n");
  250.         }
  251.         else
  252.         {
  253.           printf("FIFO没空!!!\n");
  254.         }
  255.       }

  256.       printf("\n");

  257.       {
  258.         uint8_t  rdata[256] = {0};
  259.         uint16_t len        = RingBuffer_Out(fifo, rdata, sizeof(rdata));

  260.         if(len > 0)
  261.         {
  262.           printf("从FIFO中读出的数据,长度:%d\n", len);

  263.           for(int i = 0; i < len; i++)
  264.           {
  265.             printf("%d ", rdata[i]);
  266.           }

  267.           printf("\n");

  268.           printf("FIFO读取成功,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  269.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  270.         }
  271.         else
  272.         {
  273.           printf("FIFO读取失败,FIFO大小:%d,使用大小:%d,剩余大小:%d\n",
  274.                  RingBuffer_Size(fifo), RingBuffer_Len(fifo), RingBuffer_Avail(fifo));
  275.         }

  276.         if(RingBuffer_IsFull(fifo) == true)
  277.         {
  278.           printf("FIFO满了!!!\n");
  279.         }
  280.         else
  281.         {
  282.           printf("FIFO没满!!!\n");
  283.         }

  284.         if(RingBuffer_IsEmpty(fifo) == true)
  285.         {
  286.           printf("FIFO空了!!!\n");
  287.         }
  288.         else
  289.         {
  290.           printf("FIFO没空!!!\n");
  291.         }
  292.       }

  293.       printf("\n\n\n");
  294.       Sleep(5000);
  295.     }
  296.   }
  297.   else
  298.   {
  299.     printf("FIFO创建失败\n");
  300.   }

  301.   for(;;)
  302.   {

  303.   }
  304. }
复制代码

3,运行效果
RunningResult.jpg

回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
发表于 2018-10-25 10:01:19 | 显示全部楼层
多谢分享,以Star.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-5 16:28 , Processed in 0.163781 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表