基于c 实现 FIFO
功能:
1、读和写长度不限制
2、数据操作 和 指针操作分开(如先操作数据,再操作指针)
适用场景:
单向通信模式,一方写、一方读,可用于任务间单向通信(无需锁)
如:
1、音频各个处理流程间,缓冲数据
2、线程间、进程间,cpu间,基于共享内存的大数据量传递,缓冲数据
头文件:
/** Time : 2023/12/XX* Author :*/
#ifndef __ZFIFO_H__
#define __ZFIFO_H__// #include "stdint.h"
#include "stdio.h"
#include "stdlib.h"// #define min(a, b) (((a) < (b)) ? (a) : (b))/* FIFO数据的类型,可以是结构体类型 */
typedef unsigned char u8;
typedef unsigned int u32;/* 读写偏移计数最大值1取 2*size 长度,解决取 size 大小时,当 w r 重叠时,无法区分满 或者空的问题 */
typedef struct
{u32 w; /* 写偏移计数 */u32 r; /* 读偏移计数 */u32 size; /* FIFO数据区大小 */u8 *data; /* FIFO数据区指针 */
} fifo_t;/****************************************************************** 函数功能:FIFO初始化(动态分配内存)** *参数 size:fifo数据区字节数* *返回值 创建成功:返回创建fifo指针* 创建失败:返回创建空指针******************************************************************/
fifo_t *fifo_init(u32 size);/****************************************************************** 函数功能:FIFO内存释放(和动态分配内存初始化配合使用)** *参数 f:fifo指针* *返回值 0******************************************************************/
u32 fifo_deinit(fifo_t *f);/****************************************************************** 函数功能:FIFO初始化(只初始化)** *参数 f:fifo指针* *参数 buf:fifo数据区* *参数 size:fifo数据区字节数* *返回值 0******************************************************************/
void fifo_init_ext(fifo_t *f, void *buf, u32 size);/****************************************************************** 函数功能:FIFO重置** *参数 f:fifo指针* *返回值 0******************************************************************/
u32 fifo_reset(fifo_t *f);/****************************************************************** 函数功能:获取fifo数据区已使用空间大小** *参数 f:fifo指针* *返回值 fifo数据区已使用字节数******************************************************************/
u32 fifo_getUsed(fifo_t *f);/****************************************************************** 函数功能:获取fifo数据区空余空间大小** *参数 f:fifo指针* *返回值 fifo数据区空余字节数******************************************************************/
u32 fifo_getFree(fifo_t *f);/****************************************************************** 函数功能:获取读指针位置** *参数 f:fifo指针* *返回值 读指针位置******************************************************************/
u8 *fifo_getReadPtr(fifo_t *f);/****************************************************************** 函数功能:获取写指针位置** *参数 f:fifo指针* *返回值 写指针位置******************************************************************/
u8 *fifo_getWritePtr(fifo_t *f);/****************************************************************** 函数功能:FIFO是否满** *参数 f:fifo指针* *返回值 1-满 0-未满******************************************************************/
u32 fifo_isFull(fifo_t *f);/****************************************************************** 函数功能:FIFO是否为空** *参数 f:fifo指针* *返回值 1-空 0-未空******************************************************************/
u32 fifo_isEmpty(fifo_t *f);/****************************************************************** 函数功能:FIFO读数据(不更新读指针)** *参数 f:fifo指针* *参数 buf:数据缓冲区* *参数 len:数据长度* *返回值 实际读数据长度* *注意 fifo剩余数据 < len 情况******************************************************************/
u32 fifo_readOnlyData(fifo_t *f, u8 *buf, u32 len);/****************************************************************** 函数功能:更新FIFO读指针(不读数据)** *参数 f:fifo指针* *参数 len:数据长度* *返回值 实际读出数据长度* *注意 fifo剩余数据 < len 情况* *注意 整体逻辑同读数据保持一致******************************************************************/
u32 fifo_readOnlyPtr(fifo_t *f, u32 len);/****************************************************************** 函数功能:从FIFO读数据、并更新读指针** *参数 f:fifo指针* *参数 buf:数据缓冲区* *参数 len:数据长度* *返回值 实际读出数据长度* *注意 fifo剩余数据 < len 情况* *注意 基于 fifo_readOnlyData fifo_readOnlyPtr 实现******************************************************************/
u32 fifo_read(fifo_t *f, u8 *buf, u32 len);/****************************************************************** 函数功能:FIFO写数据(不更新写指针)** *参数 f:fifo指针* *参数 buf:数据缓冲区* *参数 len:数据长度* *返回值 实际写数据长度* *注意 fifo剩余数据 < len 情况******************************************************************/
u32 fifo_writeOnlyData(fifo_t *f, u8 *buf, u32 len);/****************************************************************** 函数功能:更新FIFO写指针(不写数据)** *参数 f:fifo指针* *参数 len:数据长度* *返回值 实际写数据长度* *注意 fifo剩余数据 < len 情况* *注意 整体逻辑同写数据保持一致******************************************************************/
u32 fifo_writeOnlyPtr(fifo_t *f, u32 len);/****************************************************************** 函数功能:FIFO写数据、并更新写指针** *参数 f:fifo指针* *参数 buf:数据缓冲区* *参数 len:数据长度* *返回值 实际写数据长度* *注意 fifo剩余数据 < len 情况* *注意 基于 fifo_writeOnlyData fifo_writeOnlyPtr 实现******************************************************************/
u32 fifo_write(fifo_t *f, u8 *buf, u32 len);#endif /* __ZFIFO_H__ */
.c 函数实现:
/** Time : 2023/12/XX* Author :*/#include "fifo.h"
#include "string.h"/** init**/
fifo_t *fifo_init(u32 size)
{fifo_t *f = (fifo_t *)malloc(sizeof(fifo_t));if (NULL == f)return NULL;f->data = (u8 *)malloc(sizeof(u8) * size);if (NULL == f->data){free(f);return NULL;}f->w = 0;f->r = 0;f->size = size;return f;
}void fifo_init_ext(fifo_t *f, void *buf, u32 size)
{f->w = 0;f->r = 0;f->size = size;f->data = buf;return f;
}u32 fifo_deinit(fifo_t *f)
{if (NULL != f->data){free(f->data);f->data = NULL;}if (NULL != f){free(f->data);// f = NULL;}return 0;
}u32 fifo_reset(fifo_t *f)
{f->w = 0;f->r = 0;return 0;
}u32 fifo_getUsed(fifo_t *f)
{
#if 0u32 len;if (f->w >= f->r){len = f->w - f->r;}else{len = (f->size << 1) - f->r + f->w;}return len;
#elseif (f->w >= f->r){return (f->w - f->r);}return ((f->size << 1) - f->r + f->w);
#endif
}u32 fifo_getFree(fifo_t *f)
{
#if 0u32 len;if (f->w >= f->r){len = f->size - f->w + f->r;}else{len = f->r - f->w - f->size;}return len;
#elseif (f->w >= f->r){return (f->size - f->w + f->r);}return (f->r - f->w - f->size);
#endif
}u8 *fifo_getReadPtr(fifo_t *f)
{return (f->data + (f->r % f->size));
}u8 *fifo_getWritePtr(fifo_t *f)
{return (f->data + (f->w % f->size));
}u32 fifo_isFull(fifo_t *f)
{if (0 == fifo_getFree(f))return 1;return 0;
}u32 fifo_isEmpty(fifo_t *f)
{if (0 == fifo_getUsed(f))return 1;return 0;
}u32 fifo_readOnlyData(fifo_t *f, u8 *buf, u32 len)
{// copy len, first copy lenu32 cl, fcl;// 剩余空间 与 待读数据取小cl = fifo_getUsed(f);if (cl > len) cl = len;// 第一次读fcl = f->size - (f->r % f->size);if (fcl > cl) fcl = cl;memcpy(buf, f->data + (f->r % f->size), fcl);// 第二次读,跨buf尾的时候,从buf头开始读剩余部分if (fcl < cl)memcpy(buf + fcl, f->data, cl - fcl);return cl;
}u32 fifo_readOnlyPtr(fifo_t *f, u32 len)
{// copy lenu32 cl = fifo_getUsed(f);if (cl > len) cl = len;// 计算偏移地址f->r = (f->r + cl) % (f->size << 1);return cl;
}u32 fifo_read(fifo_t *f, u8 *buf, u32 len)
{u32 ret = 0;ret = fifo_readOnlyData(f, buf, len);ret |= fifo_readOnlyPtr(f, len);return ret;
}u32 fifo_writeOnlyData(fifo_t *f, u8 *buf, u32 len)
{// copy len, first copy lenu32 cl, fcl;// 剩余空间 与 写数据 取小cl = fifo_getFree(f);if (cl > len) cl = len;// 第一次写fcl = f->size - (f->w % f->size);if (fcl >= cl) fcl = cl;memcpy(f->data + (f->w % f->size), buf, fcl);// 第二次:buf头开始写剩余部分if (fcl < cl)memcpy(f->data, buf + fcl, cl - fcl);return cl;
}// 计算逻辑通写数据保持一致
u32 fifo_writeOnlyPtr(fifo_t *f, u32 len)
{// copy lenu32 cl = fifo_getFree(f);if (cl > len) cl = len;// 计算偏移地址f->w = (f->w + cl) % (f->size << 1);return cl;
}u32 fifo_write(fifo_t *f, u8 *buf, u32 len)
{u32 ret = 0;ret = fifo_writeOnlyData(f, buf, len);ret |= fifo_writeOnlyPtr(f, len);return ret;
}
测试程序:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include "fifo.h"#define FIFO_READ_SIZE 32
#define FIFO_WRITE_SIZE 19
#define FIFO_BUF_SIZE 32fifo_t* g_fifo;
int g_exit = 0;// 读文件线程函数
void* read_file(void* arg) { int fd = *(int*)arg; char buffer[FIFO_WRITE_SIZE + 1]; ssize_t bytes_read; while(1){if(fifo_getFree(g_fifo) >= FIFO_WRITE_SIZE){if ((bytes_read = read(fd, buffer, FIFO_WRITE_SIZE)) > 0) { if(bytes_read != fifo_write(g_fifo, buffer, bytes_read)){printf("write fifo error\n");}// if(bytes_read != FIFO_WRITE_SIZE)// printf("\n ## len = %d\n", (int)bytes_read);}else{printf("write fifo finish\n");g_exit = 1;break;}}else{usleep(2000);}}return NULL;
} // 写文件线程函数
void* write_file(void* arg) { int fd = *(int*)arg; char buffer[FIFO_READ_SIZE + 1]; ssize_t bytes_written;int fifo_size = 0;while(1){fifo_size = fifo_getUsed(g_fifo);if(fifo_size >= FIFO_READ_SIZE){if (FIFO_READ_SIZE != fifo_read(g_fifo, buffer, FIFO_READ_SIZE)){printf("read fifo error\n");}else{write(fd, buffer, FIFO_READ_SIZE);}}else if(fifo_size >= 0){if (fifo_size != fifo_read(g_fifo, buffer, fifo_size)){printf("read fifo error\n");}else{write(fd, buffer, fifo_size);}}else{usleep(2000);}if(fifo_isEmpty(g_fifo) && g_exit) {printf("read fifo finish\n");break;}}return NULL;
} int main() { pthread_t read_thread, write_thread; int fd_in, fd_out;g_fifo = fifo_init((u32)FIFO_BUF_SIZE); // 打开输入文件和输出文件 fd_in = open("input.txt", O_RDONLY); fd_out = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); // 创建读文件线程和写文件线程 pthread_create(&read_thread, NULL, read_file, &fd_in); pthread_create(&write_thread, NULL, write_file, &fd_out); // 等待两个线程执行完毕 pthread_join(read_thread, NULL); pthread_join(write_thread, NULL); // 关闭文件描述符 close(fd_in); close(fd_out); fifo_deinit(g_fifo);return 0;
}
相关文章:
基于c 实现 FIFO
功能: 1、读和写长度不限制 2、数据操作 和 指针操作分开(如先操作数据,再操作指针) 适用场景: 单向通信模式,一方写、一方读,可用于任务间单向通信(无需锁) 如&…...
tortoisegit 报错:server refused to start a shell/command
原因:阿里云的云效不支持TortoiseGit 使用 TortoiseGitPlink,请修改为 OpenSSH。 官网修改教程:TortoiseGit 工具相关报错如何处理? 基本流程: 选择设置(Settings),选择通用&#x…...
电商平台API接口指南,京东商品详情接口,京东详情页接口,宝贝详情页接口,商品属性接口,商品信息查询,商品详细信息接口,h5实时详情页数据展示
京东商品详情API接口是京东开放平台提供的一种API接口,通过该接口,可以获取到京东商品的详细信息,如商品名称、价格、图片和描述等信息。 使用方法如下: 注册并获取API密钥:首先需要在京东开放平台上注册并获取API密…...
什么是迁移学习
1 迁移学习概述 迁移学习(Transfer Learning)是机器学习中的一种方法,它允许模型将从一个任务中学到的知识应用到另一个相关的任务中。这种方法在数据稀缺的情况下尤为有用,因为它减少了对大量标记数据的需求。迁移学习已成为深度…...
万宾科技水环境综合治理监测系统的融合与应用
随着社会经济的快速发展,我国的水环境污染问题日益凸显,这不仅对生态环境造成了严重破坏,也严重威胁到人民群众的健康和生活质量。为了解决这一问题,城市生命线与水环境综合治理监测系统应运而生,二者的结合将为水环境…...
【EI会议征稿】第三届图像,信号处理与模式识别国际学术会议(ISPP 2024)
第三届图像,信号处理与模式识别国际学术会议(ISPP 2024) 2024 3rd International Conference on Image, Signal Processing and Pattern Recognition(ISPP 2024) 第三届图像,信号处理与模式识别国际学术会议…...
继阿里云、滴滴、语雀后,腾讯视频也出现重大系统故障
昨晚,许多网友报告称腾讯视频出现了网络故障,具体表现为首页无法加载内容、VIP 用户无法观看会员视频等问题。 针对这一问题,腾讯视频回应称:目前腾讯视频遇到了暂时的技术问题,正在紧急修复中,各项功能正在…...
kotlin中sealed语句的使用
sealed 密封类是 Kotlin 中的一种特殊类别,它的主要作用是限制类的继承结构。密封类用于表示受限的类继承结构,即一个值只能有有限几种类型,而不能有任意类型。密封类通常用于表示一种有限集合的类型。 下面是密封类的主要特性和作用&#x…...
软信天成:数据泄露日趋严重 “资产”保护何去何从
随着数据应用的逐渐深入,越来越多的企业意识到:数据作为信息的载体,可以成为企业知识产权、收益流和具备竞争优势的基础资产。然而,当包含大量敏感信息的数据被视作资产时,亦将直面信息被“窃取”、“泄露”和“滥用”…...
GitHub打不开的解决方案(百试不爽法)
一、githup首先打开以下网址,搜索 DNS Resource Records 找到对应的IP地址信息 1、点击访问 GitHub.com - GitHub: Lets build from here GitHubGitHub is the best place to share code with friends, co-workers, classmates, and complete strangers. Over fo…...
一文入门Python面向对象编程(干货满满)
在开始之前,我一直企图找到一个通俗直观的例子来介绍面向对象。找来找去,发现什么都可以是面向对象,什么又都不是面向对象。后来我发现,人类认识社会的方式更多的就是面向对象的方式。“物以类聚、人以群分”,这句话好…...
qiankun: 关于ElementUI字体图标加载不出来的问题
问题描述: 子应用使用的是vueelementUI,在项目main.js中需要引入elementUI的样式文件。elementUI的样式文件中有字体文件的引用,是以相对路径的形式写在css文件中的, 本来独立部署项目访问是没问题的,问题出现在以qi…...
【智能家居】四、网络服务器线程控制功能点
网络控制 网络线程控制功能点代码 inputCommand.h(输入控制指令)socketControl.c(socket网络控制指令)main.c(主函数)编译运行结果 网络控制 Linux网络编程 “网络控制”(Network Control&a…...
localForage使用 IndexedDB / WebSQL存储
一、什么是 localForage 当我们的存储量比较大的时候,我们一定会想到我们的 indexedDB,让我们在浏览器中也可以 使用数据库这种形式来玩转本地化存储,然而 indexedDB 的使用是比较繁琐而复杂的, 有一定的学习成本,但 …...
Hdoop学习笔记(HDP)-Part.03 资源规划
目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …...
SQL -高阶3
zstarling 字符串拼接与类型转换最大,最小值,提取日期部分的数值日期截断 字符串拼接与类型转换 新语法SQL delete from public.basiclaw_qr_staff_ac ct where batch_date || data_dt || :: date and biz_line || biz_line || ;详解 该 SQL 语句…...
HarmonyOS4.0系列——03、声明式UI、链式编程、事件方法、以及自定义组件简单案例
HarmonyOS4.0系列——03、声明式UI、链式编程、事件方法、以及自定义组件简单案例 声明式 UI ArkTS以声明方式组合和扩展组件来描述应用程序的UI,同时还提供了基本的属性、事件和子组件配置方法,帮助开发者实现应用交互逻辑。 如果组件的接口定义没有包…...
播放器开发(六):音频帧处理并用SDL播放
目录 学习课题:逐步构建开发播放器【QT5 FFmpeg6 SDL2】 步骤 AudioOutPut模块 1、初始化【分配缓存、读取信息】 2、开始线程工作【从队列读帧->重采样->SDL回调->写入音频播放数据->SDL进行播放】 主要代码 分配缓存 // 对于样本队列 av_audio_…...
Qt 问题记录
问题记录 运行时出现的问题 运行出现的warning QWidget::repaint: Recursive repaint detected在paintEvent中使用painter绘制了线段、图片,移动了QWidget,加入了下面代码导致的 QApplication::processEvents();屏蔽后没有出现该warning QApplicati…...
Go 语言真正有什么用处?
在其十几年的发展过程中,Google 的Go 编程语言已经从 alpha 极客的好奇心发展成为世界上一些最重要的云原生软件项目背后经过考验的编程语言。 为什么Docker、Kubernetes等项目的开发者会选择 Go ?Go 的定义特征是什么?它与其他编程语言有何…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
