|
Linux下的KFIFO. 限制是缓存区大小必须为2的整数次幂.
在Linux内核中, 程序会将用户输入的缓存区自动圆整到2的整数次幂.
- /**
- ******************************************************************************
- * @file kfifo.c
- * @author DevLabs
- * @version V0.1
- * @date 2013-12-30 20:44
- * @brief
- ******************************************************************************
- * @attention
- *
- * <br />Copyright 2013
- * <br />http://www.DevLabs.cn
- *
- * <h2><center>© COPYRIGHT 2013 DevLabs </center></h2>
- ******************************************************************************
- */
- /* Includes ------------------------------------------------------------------*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- /* Private typedef -----------------------------------------------------------*/
- typedef struct
- {
- uint8_t *buffer; //!< 缓存区指针
- uint32_t size; //!< 缓存区大小
- uint32_t in; //!< 写偏移(in % size)
- uint32_t out; //!< 读偏移(out % size)
- } KFIFO;
- /* Private define ------------------------------------------------------------*/
- #ifndef BOOL
- #define BOOL unsigned int
- #endif
- #ifndef FALSE
- #define FALSE (0)
- #endif
- #ifndef TRUE
- #define TRUE (!FALSE)
- #endif
- #define FIFO_BUF_SIZE 32
- /* Private macro -------------------------------------------------------------*/
- #define MIN(a, b) ((a) < (b) ? (a) : (b))
- #define MAX(a, b) ((a) < (b) ? (b) : (a))
- /* Private variables ---------------------------------------------------------*/
- /* Private function prototypes -----------------------------------------------*/
- /* Private functions ---------------------------------------------------------*/
- /**
- * @brief 判断一个数是否为2的整数次幂
- *
- * @param n 要判断的数
- *
- * @retval TRUE
- * @retval FALSE
- */
- BOOL is_power_of_2(unsigned long n)
- {
- return (n != 0 && ((n & (n - 1)) == 0));
- }
- /**
- * @brief fifo初始化
- *
- * @param fifo 要初始化的fifo
- * @param buffer fifo的缓冲区
- * @param size fifo缓冲大小
- *
- * @retval TRUE 初始化成功
- * @retval FALSE 初始化失败
- */
- BOOL kfifo_init(KFIFO *fifo, uint8_t *buffer, uint32_t size)
- {
- if (!is_power_of_2(size))
- {
- printf("file: %s, line: %d size must be power of 2!", __FILE__, __LINE__);
- return FALSE;
- }
- fifo->buffer = buffer;
- fifo->size = size;
- fifo->in = fifo->out = 0;
- return TRUE;
- }
- /**
- * @brief 向FIFO写入数据
- *
- * @param fifo 待写入的FIFO
- * @param buffer 待写入的数据
- * @param len 待写入的数据长度
- *
- * @return 实际写入的数据
- */
- uint16_t kfifo_put(KFIFO *fifo, uint8_t *buffer, uint32_t len)
- {
- uint32_t l;
- len = MIN(len, fifo->size - (fifo->in - fifo->out));
- l = MIN(len, fifo->size - (fifo->in & (fifo->size - 1)));
- memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
- memcpy(fifo->buffer, buffer + l, len - l);
- fifo->in += len;
- return len;
- }
- /**
- * @brief 从FIFO取出数据
- *
- * @param fifo 要取出数据的FIFO
- * @param buffer 存储取出数据的缓存
- * @param len 要取出数据的长度
- *
- * @return 实际取出的数据长度
- */
- uint16_t kfifo_get(KFIFO *fifo, uint8_t *buffer, uint32_t len)
- {
- uint32_t l;
- len = MIN(len, fifo->in - fifo->out);
- l = MIN(len, fifo->size - (fifo->out & (fifo->size - 1)));
- memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
- memcpy(buffer + l, fifo->buffer, len - l);
- fifo->out += len;
- return len;
- }
- /**
- * @brief 打印缓冲区
- *
- * @param buf 缓冲区指针
- * @param len 要打印的数据长度
- */
- void put_buf(const uint8_t *buf, uint32_t len)
- {
- while (len != 0)
- {
- putchar(*buf);
- len--;
- buf++;
- }
- printf("\n");
- return;
- }
- int main(void)
- {
- KFIFO kfifo;
- uint32_t i;
- uint8_t fifo_buf[FIFO_BUF_SIZE];
- uint8_t get_buf[FIFO_BUF_SIZE];
- uint8_t *str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- uint8_t *str2 = "abcdefghijklmhopqrstuvwxyz";
- for (i = 0; i < FIFO_BUF_SIZE; i++)
- {
- fifo_buf[i] = '*';
- }
- for (i = 0; i < FIFO_BUF_SIZE; i++)
- {
- get_buf[i] = '#';
- }
- // FIFO初始化
- kfifo_init(&kfifo, fifo_buf, FIFO_BUF_SIZE);
- // 向FIFO写入26个数据
- kfifo_put(&kfifo, str1, strlen(str1));
- printf("fifo_buf: ");
- put_buf((const uint8_t *)&fifo_buf, FIFO_BUF_SIZE);
- // 取出10个数据
- kfifo_get(&kfifo, get_buf, 10);
- printf(" get_buf: ");
- put_buf((const uint8_t *)&get_buf, FIFO_BUF_SIZE);
- // 这次写入会使FIFO回绕
- kfifo_put(&kfifo, str2, strlen(str2));
- printf("fifo_buf: ");
- put_buf((const uint8_t *)&fifo_buf, FIFO_BUF_SIZE);
- return 0;
- }
- /******************* (C) COPYRIGHT 2013 DevLabs **********END OF FILE**********/
复制代码 |
|