新增动态申请内存方法,可进行内存回收。完善注释

This commit is contained in:
2025-08-15 17:41:19 +08:00
commit 966fed011c
5 changed files with 586 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build/

36
CMakeLists.txt Executable file
View File

@@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.20)
project(My_ptotocol VERSION 0.1 LANGUAGES CXX C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_COMPILER gcc)
set(CMAKE_C_STANDARD_REQUIRED ON)
# set(CMAKE_CXX_STANDARD 23)
# set(CMAKE_CXX_COMPILER g++)
# set(CMAKE_CXX_STANDARD_REQUIRED ON)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
include_directories(
.
src/lib
)
set(PROJECT_SOURCES
src/main.c
src/lib/kfifo/kfifo.c
)
add_executable(${PROJECT_NAME}
${PROJECT_SOURCES}
)
target_link_libraries(${PROJECT_NAME}
)
include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME}
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

366
src/lib/kfifo/kfifo.c Executable file
View File

@@ -0,0 +1,366 @@
/**
* @file kfifo.c
* @author guishenking (guishenking@outlook.com)
* @brief
* @version 0.1
* @date 2025-08-15
*
* @copyright Copyright (c) 2025
*
*/
#include "kfifo.h"
#include <string.h>
#include <stdlib.h>
/**
* @brief 获取 FIFO 数据起始位置
*
*/
#define KFIFO_POOL_PTR(_fifo) ((uint8_t *)_fifo->pool)
/**
* @brief 获取写入位置偏移量
*
* @param[in] fifo
* @return uint32_t
*/
#define kfifo_offset_in(_fifo_ptr) ((_fifo_ptr)->in & (_fifo_ptr)->mask)
/**
* @brief 获取读取位置偏移量
*
* @param[in] fifo
* @return uint32_t
*/
#define kfifo_offset_out(_fifo_ptr) ((_fifo_ptr)->out & (_fifo_ptr)->mask)
/**
* @brief 计算从当前读取位置偏移 _seek 后的新位置在缓冲区中的实际偏移。
*
*/
#define kfifo_offset_seek_out(_fifo_ptr, _seek) \
(((_fifo_ptr)->out + (_seek)) & (_fifo_ptr)->mask)
/**
* @brief 获取写入位置到缓冲区末尾的空间大小
*
* @param[in] fifo
* @return uint32_t
*/
#define kfifo_remain_in(_fifo_ptr) \
(kfifo_size(_fifo_ptr) - kfifo_offset_in(_fifo_ptr))
/**
* @brief 获取读取位置到缓冲区末尾的空间大小
*
* @param[in] fifo
* @return uint32_t
*/
#define kfifo_remain_out(_fifo_ptr) \
(kfifo_size(_fifo_ptr) - kfifo_offset_out(_fifo_ptr))
/**
* @brief
*
*/
#define kfifo_remain_seek_out(_fifo_ptr, _seek) \
(kfifo_size(_fifo_ptr) - kfifo_offset_seek_out(_fifo_ptr, _seek))
/**
* @brief 通过申请内存的方式初始化 FIFO使得内存可回收
*
* @param size
* @return kfifo_t*
*/
kfifo_t* kfifo_init_dynamic(uint32_t size) {
// 检查size是否为2的幂
if ((size & (size - 1)) != 0) return NULL;
// 分配缓冲区和控制结构
uint8_t *pool = (uint8_t*)malloc(size);
if (!pool) return NULL;
kfifo_t *fifo = (kfifo_t*)malloc(sizeof(kfifo_t));
if (!fifo) { free(pool); return NULL; }
// 初始化结构体
fifo->in = 0;
fifo->out = 0;
fifo->mask = size - 1;
fifo->pool = pool;
fifo->method = KFIFO_CREATED_METHOD_DYNAMIC; // 设置为动态创建方法
return fifo;
}
/**
* @brief 销毁通过申请内存方式创建的 FIFO
*
* @param fifo
* @return true success destroyed memory
* @return false failed Memery was created by static method
*/
bool kfifo_destroy(kfifo_t *fifo) {
if (fifo->method == KFIFO_CREATED_METHOD_STATIC) {
return false; // 静态创建的 FIFO 不允许销毁
}
if (fifo) {
if(fifo->pool == NULL) {
free(fifo); // 如果 pool 已经是 NULL直接释放 fifo
return false; // 如果 pool 已经是 NULL直接返回
}
free(fifo->pool);
fifo->pool = NULL; // 清空指针,避免悬挂指针
free(fifo);
fifo = NULL; // 清空指针,避免悬挂指针
return true; // 成功销毁
}
return false; // 如果 fifo 是 NULL直接返回 false
}
/**
* @brief 初始化FIFO
* @note 使用@kfifo_def 定义的fifo无需调用此函数
* @param[in] fifo
* @param[in] pool fifo 数据缓冲区
* @param[in] size fifo 大小必须是2的幂次
* @return int
* @retval -1 参数错误、pool对齐错误
* @retval 0 初始化完成
*/
bool kfifo_init_static(kfifo_t *fifo, uint8_t *pool, uint32_t size) {
/* 判断参数是否正确 */
if ((NULL == fifo) || (NULL == pool) || (size & size - 1)) {
return false;
}
fifo->in = 0;
fifo->out = 0;
fifo->pool = pool;
fifo->mask = size - 1;
fifo->method = KFIFO_CREATED_METHOD_STATIC; // 设置为静态创建方法
return true; // 初始化成功
}
/**
* @brief 向 in 位置写入一个字节
*
* @param fifo
* @param data
* @return true
* @return false
*/
bool kfifo_put_byte(kfifo_t *fifo, uint8_t data) {
if (NULL == fifo) {
return false; // 参数错误
}
if (kfifo_is_full(fifo)) {
return false;
}
KFIFO_POOL_PTR(fifo)[kfifo_offset_in(fifo)] = data;
fifo->in++;
return true;
}
/**
* @brief 从 out 位置获取一个字节
*
* @param fifo
* @param data
* @return int
*/
bool kfifo_get_byte(kfifo_t *fifo, uint8_t *data) {
if ((NULL == fifo) || (NULL == data)) {
return false; // 参数错误
}
if (kfifo_is_empty(fifo)) {
return false;
}
*data = KFIFO_POOL_PTR(fifo)[kfifo_offset_out(fifo)];
fifo->out++;
return true;
}
/**
* @brief 写入数据块
* @note 当fifo空间不足时会对 data 进行截断处理
* @param[in] fifo
* @param[in] data
* @param[in] len
* @return int 返回写入的数据大小
*/
int kfifo_in(kfifo_t *fifo, const uint8_t *data, uint32_t len) {
uint32_t avail = kfifo_avail(fifo);
if (len > avail) {
len = avail;
}
if (len == 0) {
return 0;
}
if (kfifo_remain_in(fifo) < len) {
memcpy(fifo->pool + kfifo_offset_in(fifo),
data,
kfifo_remain_in(fifo));
memcpy(fifo->pool,
data + kfifo_remain_in(fifo),
len - kfifo_remain_in(fifo));
} else {
memcpy(fifo->pool + kfifo_offset_in(fifo),
data,
len);
}
fifo->in += len;
return len;
}
/**
* @brief 读取数据块
*
* @param fifo
* @param buffer
* @param size
* @return int
*/
int kfifo_out(kfifo_t *fifo, uint8_t *buffer, uint32_t size) {
uint32_t used = kfifo_used(fifo);
if (size > used) {
size = used;
}
if (0 == size) {
return 0;
}
if (kfifo_remain_out(fifo) < size) {
memcpy(buffer, fifo->pool + kfifo_offset_out(fifo), kfifo_remain_out(fifo));
memcpy(buffer + kfifo_remain_out(fifo),
fifo->pool,
size - kfifo_remain_out(fifo));
} else {
memcpy(buffer,
fifo->pool + kfifo_offset_out(fifo),
size);
}
fifo->out += size;
return size;
}
/**
* @brief 获取 fifo 数据指针偏移位置
*
* @param[in] fifo
* @param[in] ptr
* @return int 可连续读取的数据数量
* @retval 0 fifo is empty
*/
int kfifo_peek(kfifo_t *fifo, const uint8_t **ptr) {
int linear;
*ptr = NULL;
if (kfifo_is_empty(fifo)) {
return 0;
}
*ptr = &KFIFO_POOL_PTR(fifo)[kfifo_offset_out(fifo)];
if (kfifo_offset_in(fifo) <= kfifo_offset_out(fifo)) {
linear = kfifo_remain_out(fifo);// 数据在缓冲区末尾
} else {
linear = kfifo_used(fifo);// 数据未跨缓冲区末尾
}
return linear;
}
/**
* @brief 获取偏移 seek 后的数据指针(模拟读取后位置)。
*
* @param fifo
* @param ptr
* @param seek
* @return int
*/
int kfifo_peek_seek(kfifo_t *fifo, const uint8_t **ptr, uint32_t seek) {
*ptr = NULL;
if (kfifo_used(fifo) < seek) {
return 0;
}
// *ptr = &KFIFO_POOL_PTR(fifo)[kfifo_offset_seek_out(fifo, seek)];
*ptr = (uint8_t*)fifo->pool + kfifo_offset_seek_out(fifo, seek);
if (kfifo_remain_out(fifo) > seek) {
seek = kfifo_remain_seek_out(fifo, seek);
} else {
seek = kfifo_used(fifo) - seek;
}
return seek;
}
/**
* @brief 复制数据到 buffer 但不移动 out 指针。
*
* @param[in] fifo
* @param[in] buffer 存储数据的缓冲区
* @param[in] size 需要复制的数据量
* @return int
* @return -1 参数错误
*/
int kfifo_peek_block(kfifo_t *fifo, uint8_t *buffer, uint32_t size) {
int temp;
if ((NULL == fifo) || (NULL == buffer) || (0 == size)) {
return -1;
}
/* FIFO 中的数据量 */
temp = kfifo_used(fifo);
if (!temp) {
return 0;
}
if (size > temp) {
size = temp;
}
temp = kfifo_remain_out(fifo);
if (size > temp) {
memcpy(buffer, fifo->pool + kfifo_offset_out(fifo), temp);
memcpy(buffer + temp,
fifo->pool,
size - temp);
} else {
memcpy(buffer,
fifo->pool + kfifo_offset_out(fifo),
size);
}
return size;
}
/**
* @brief 丢弃seek个字节
*
* @param fifo
* @param seek 偏移量
* @return int
*/
int kfifo_seek(kfifo_t *fifo, uint32_t seek) {
if (kfifo_used(fifo) < seek) {
seek = kfifo_used(fifo);
}
fifo->out += seek;
return seek;
}

143
src/lib/kfifo/kfifo.h Executable file
View File

@@ -0,0 +1,143 @@
/**
* @file kfifo.h
* @author guishenking (guishenking@outlook.com)
* @brief
* @version 0.1
* @date 2025-08-15
*
* @copyright Copyright (c) 2025
*
*/
#ifndef _KFIFO_H_
#define _KFIFO_H_
#include <stdint.h>
#include <stdbool.h>
enum kfifo_created_method {
KFIFO_CREATED_METHOD_STATIC = 0, /*!< 静态创建 */
KFIFO_CREATED_METHOD_DYNAMIC, /*!< 动态创建 */
};
/**
* @brief kfifo 结构定义
*
*/
typedef struct kfifo {
uint32_t in; /*!< 输入数据下标, 对于单片机使用 volatile 修饰 */
uint32_t out; /*!< 输出数据下标, 对于单片机使用 volatile 修饰 */
uint32_t mask;/*!< 缓冲区大小掩码, size - 1 */
uint8_t *pool;/*!< 数据缓冲区指针 */
enum kfifo_created_method method;/*!< FIFO 创建方法 */
}kfifo_t;
/**
* @brief kfifo 初始化器
*
* @param[in] _pool FIFO数据缓冲区
* @param[in] _size 缓冲区大小
*/
#define kfifo_initializer(_pool, _size) \
{ 0, 0, _size - 1, _pool, KFIFO_CREATED_METHOD_STATIC, }
/**
* @brief 定义 KFIFO
*
* @param[in] _name FIFO名称
* @param[in] _size 缓冲区大小必须是2的幂次
*/
#define kfifo_def(_name, _size) \
static uint8_t _##_name##_pool[_size]; \
static kfifo_t _name = kfifo_initializer(_##_name##_pool, _size)//初始化fifo
#ifdef __cplusplus
extern "C" {
#endif
//静态创建fifo
bool kfifo_init_static(kfifo_t *fifo, uint8_t *pool, uint32_t size);
//动态创建fifo
kfifo_t* kfifo_init_dynamic(uint32_t size);
//销毁动态创建的fifo
bool kfifo_destroy(kfifo_t *fifo) ;
//向fifo写入一个字节
bool kfifo_put_byte(kfifo_t *fifo, uint8_t data);
//从fifo读取一个字节
bool kfifo_get_byte(kfifo_t *fifo, uint8_t *data);
//写入数据块
int kfifo_in(kfifo_t *fifo, const uint8_t *data, uint32_t len);
//读取数据块
int kfifo_out(kfifo_t *fifo, uint8_t *data, uint32_t size);
//获取fifo数据指针
int kfifo_peek(kfifo_t *fifo, const uint8_t **ptr);
//从获取偏移位置的数据指针
int kfifo_peek_seek(kfifo_t *fifo, const uint8_t **ptr, uint32_t seek);
//从fifo读取数据块不改变 fifo 状态
int kfifo_peek_block(kfifo_t *fifo, uint8_t *buffer, uint32_t size);
//丢弃fifo部分数据
int kfifo_seek(kfifo_t *fifo, uint32_t seek);
/**
* @brief 清空 FIFO
*
*/
#define kfifo_clear(_fifo_ptr) \
do { \
(_fifo_ptr)->in = 0; \
(_fifo_ptr)->out = 0; \
} while(0)
/**
* @brief 获取fifo大小
*
* @param[in] fifo
* @return uint32_t
*/
#define kfifo_size(_fifo_ptr) ((_fifo_ptr)->mask + 1)
/**
* @brief 获取当前存储的数据量
*
* @param[in] fifo
* @return uint32_t
*/
#define kfifo_used(_fifo_ptr) \
(((kfifo_size(_fifo_ptr)) + (_fifo_ptr)->out) == (_fifo_ptr)->in \
? kfifo_size(_fifo_ptr) \
: (((_fifo_ptr)->in - (_fifo_ptr)->out) & (_fifo_ptr)->mask))
/**
* @brief 获取空闲空间大小
*
* @param[in] fifo
* @return uint32_t
*/
#define kfifo_avail(_fifo_ptr) (kfifo_size(_fifo_ptr) - kfifo_used(_fifo_ptr))
/**
* @brief 判断 FIFO 是否已满
*
*/
#define kfifo_is_full(_fifo_ptr) (kfifo_avail(_fifo_ptr) == 0)
/**
* @brief 判断 FIFO 是否为空
*
*/
#define kfifo_is_empty(_fifo_ptr) (kfifo_used(_fifo_ptr) == 0)
#ifdef __cplusplus
}
#endif
#endif
/* !_KFIFO_H_ */

40
src/main.c Executable file
View File

@@ -0,0 +1,40 @@
/**
* @file main.c
* @author guishenking (guishenking@outlook.com)
* @brief
* @version 0.1
* @date 2025-07-24
*
* @copyright Copyright (c) 2025
*
*/
#include "lib/kfifo/kfifo.h"
#include <stdint.h>
#include <stddef.h>
#include <string.h>
kfifo_def(fifo,1024);
int main(){
// 示例数据
uint8_t src_data[] = {0x01, 0x02, 0x03, 0x04, 0x05};
size_t src_length = sizeof(src_data);
uint8_t dest_data[1024];
size_t dest_length = sizeof(dest_data);
uint32_t offset;
memset(dest_data, 0, dest_length); // 清空目标数据缓冲区
kfifo_in(&fifo, dest_data, dest_length); // 将数据写入FIFO
int ret = kfifo_peek_block(&fifo, dest_data, dest_length); // 从FIFO读取数据
memset(src_data, 0, src_length); // 清空源数据缓冲区
// 解码数据
kfifo_seek(&fifo, offset); // 根据偏移量调整FIFO读取位置
return 0;
}