队列实现(基于内存池思想)

1. 阅读公司代码的时候,发现公司代码向串口打印,先把数据加载到数组中,进入临界区,然后通过串口输出,退出临界区。

2. 当然还有向flash写数据,直接一次性原文写入,也没进入临界区,挂起任务调度,

3. 网络数据发送的时候,也是直接发送,而发送的数据量过大,已经出现好多关于网络发送时,芯片往接口丢数据过大,过快导致发送失败。

似乎所有的这种输入大于输出的问题,都会存在,如果强制关中断,或挂起任务调度,确实可以解决,但是我认为这样速度就下降了。

我想到的方法是,通过增加缓存,往缓存写入数据,但是我们必须清楚,大数据时缓存必定会满,这个时候肯定需要涉及动态内存申请(内存池,内存堆,可能内存池会对内存使用会造成一定的浪费,但是速度会很快)。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>/*
1.定一个小*/
typedef struct cache_simple {struct cache_simple* cache_next;unsigned int buf_len;unsigned char buf[0];
}cache_simple_t;typedef struct cache{unsigned char* data_head;unsigned char* data_tail;unsigned int block_size;cache_simple_t* cache_next;
}cache_t;void init_my_cache(cache_t* cache_head, unsigned int block_size)
{cache_simple_t* my_cache = (cache_t*)malloc(sizeof(cache_simple_t) + block_size);if (!my_cache) {return;}my_cache->buf_len = block_size;my_cache->cache_next = NULL;cache_head->cache_next = my_cache;cache_head->data_head = my_cache->buf;cache_head->data_tail = my_cache->buf;cache_head->block_size = block_size;
}static void insert_cache(cache_t* cache_head, unsigned int size)//尾插
{cache_simple_t* p = cache_head->cache_next;cache_simple_t* new_cache = (cache_simple_t*)malloc(sizeof(cache_simple_t) + size);if (new_cache == NULL) {return;}while (p->cache_next) {p = p->cache_next;}p->cache_next = new_cache;new_cache->buf_len = size;new_cache->cache_next = NULL;
}//static void delet_cache(cache_t* cache_head)//头删
//{
//	cache_simple_t* p = cache_head->cache_next;
//
//	if (p) {
//		cache_head->cache_next = p->cache_next;
//		free(p);
//	}
//}void insert_data(cache_t* cache_head, unsigned char* buf, unsigned int len)
{cache_simple_t* p = cache_head->cache_next;cache_t* p_head = cache_head;unsigned int malloc_size;unsigned int block_num, i;while (p->cache_next){p = p->cache_next;}/* 数据尾指针总是指向最后, 如果要插入数据, 要计算申请多少块block_size的内存来存储 */if (p_head->data_tail + len > p->buf + p->buf_len) {malloc_size = len - (unsigned int)(p->buf + p->buf_len - p_head->data_tail);block_num = malloc_size / p_head->block_size + ((malloc_size % p_head->block_size) ? 1 : 0);for (i = 0; i < block_num; i++) {insert_cache(p_head, p_head->block_size);}}/* 将数据存入申请的内存中 */for (i = 0; i < len; i++) {*p_head->data_tail = buf[i];if (p_head->data_tail == p->buf + p_head->block_size -1) {p_head->data_tail = p->cache_next->buf;p = p->cache_next;} else {p_head->data_tail++;}}}void display_list(cache_t* cache)
{cache_simple_t* p = cache->cache_next;unsigned int i;while (p) {for (i = 0; i < cache->block_size; i++) {printf("%c ", p->buf[i]);}p = p->cache_next;}
}unsigned int read_data(cache_t* cache, unsigned char* data)
{cache_simple_t* p = cache->cache_next;/* 如果数据头尾指针相等, 则此时链表中数据为空 */if (cache->data_head == cache->data_tail) {cache->data_head = cache->data_tail = cache->cache_next->buf;return 0;}/* 数据头指针指向的就是数据 */*data = *cache->data_head;/* 数据头指针必定在cache_head指向的第一结点 */if (cache->data_head == p->buf + cache->block_size - 1) {if (p->cache_next) {/* 只有当前结点的下一个结点不为空,才能将数据指针指向下一位置, 并删除当前这个结点 */cache->data_head = p->cache_next->buf;cache->cache_next = p->cache_next;free(p);}}else {cache->data_head++;}if (cache->data_head == cache->data_tail) {cache->data_head = cache->data_tail = cache->cache_next->buf;}return 1;
}
unsigned int read_ndata(cache_t* cache, unsigned char* data, unsigned int len) 
{unsigned int i, read_len = 0;for (i = 0; i < len; i++){if (read_data(cache, data + i)) {read_len++;}}return read_len;
}
char * str = "123456789qwertyuiopasdfghjkl";
char * str1 = "mnbvcxzlk";
void main()
{int i, len;unsigned char data[100];cache_t cache;init_my_cache(&cache, 10);insert_data(&cache, str, strlen(str));len = read_ndata(&cache, data, 28);for (i = 0; i < len; i++){printf("%c ", data[i]);}printf("\n");insert_data(&cache, str1, strlen(str1));display_list(&cache);while (1);
}

如果我们是单纯的写入数据, 串口打印,lwip发送这样没问题, 但是考虑到这个要用到对flash的操作, 意味着内部写入的数据, 要附带地址起始位置, 写入的数据, 数据长度,通通写道这个buf中, 然后底层接口读取的时候, 就需要获取这些信息, 并且读取数据

代码没在实际项目跑过, 并且这里面的内存分配malloc是有问题的, 如果是跑的裸机, 请使用我的另一篇内存池设计实现, 当然也可以把内存池跑到RTOS中, 或者直接使用RTOS的内存管理算法, 如果可以希望朋友们帮忙一起验证一下这篇和内存池.实际上内存池就是我打算设计给到这里来使用的.

这里实际就是一个队列的实现, 当数据一个一个入队, 当入队的数据满了一个预先申请的块, 则会重新申请相同大小的一块, 继续存储数据. 出队的时候, 一个数据一个数据的出, 当出完一个存储块, 则释放这段内存, 如果出到最后一块, 是不会把这块删除的, 同时如果队列为空了, 则链表指针会恢复到当前内存块的起始位置.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/130719.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【CIO人物展】黄淮学院副CIO周鹏:构建数智化平台赋能学校高质量发展

周鹏 本文由黄淮学院副CIO周鹏投递并参与《2023中国数智化转型升级优秀CIO》榜单/奖项评选。丨推荐企业—锐捷网络 大数据产业创新服务媒体 ——聚焦数据 改变商业 黄淮学院是2004年经教育部批准成立的一所省属全日制普通本科高校。学校位于素有“豫州之腹地、天下之最中”之美…

第十七节——指令

一、概念 在Vue.js中&#xff0c;指令&#xff08;Directives&#xff09;是一种特殊的语法&#xff0c;用于为HTML元素添加特定的行为和功能。指令以v-作为前缀&#xff0c;通过在HTML标签中使用这些指令来操作DOM&#xff0c;修改元素的属性、样式或行为。 Vue.js提供了一组…

地理信息系统原理-空间数据结构(7)

​四叉树编码 1.四叉树编码定义 四叉树数据结构是一种对栅格数据的压缩编码方法&#xff0c;其基本思想是将一幅栅格数据层或图像等分为四部分&#xff0c;逐块检查其格网属性值&#xff08;或灰度&#xff09;&#xff1b;如果某个子区的所有格网值都具有相同的值&#xff0…

Linux----------------Shell重定向输入输出

&#xff08;一&#xff09; 标准输入 以键盘读取用户输入的数据&#xff0c;然后再把数据拿到 Shel程序中使用。 标准输出 Shell 程序产生的数据&#xff0c;这些数据一般都是呈现到显示器上供用户浏览查看 输入输出重定向 输入方向就是数据从哪里流向程序。数据默认从键…

Flink SQL Over 聚合详解

Over 聚合定义&#xff08;⽀持 Batch\Streaming&#xff09;&#xff1a;**特殊的滑动窗⼝聚合函数&#xff0c;拿 Over 聚合 与 窗⼝聚合 做对⽐。 窗⼝聚合&#xff1a;不在 group by 中的字段&#xff0c;不能直接在 select 中拿到 Over 聚合&#xff1a;能够保留原始字段…

【使用Python编写游戏辅助工具】第五篇:打造交互式游戏工具界面:PySide6/PyQT高效构建GUI工具

前言 这里是【使用Python编写游戏辅助工具】的第五篇&#xff1a;打造交互式游戏工具界面&#xff1a;PySide6/PyQT高效构建GUI工具。本文主要介绍使用PySide6来实现构建GUI工具。 在前面&#xff0c;我们实现了两个实用的游戏辅助功能&#xff1a; 由键盘监听事件触发的鼠标连…

IntelliJ IDEA 2023 最新版如何试用?IntelliJ IDEA 2023最新版试用方法及验证ja-netfilter配置成功提示

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

文件上传学习笔记

笔记 文件上传 文件上传是指将本地图片&#xff0c;视频&#xff0c;音频等文件上传到服务器&#xff0c;供其它用户浏览或下载的过程 文件上传前端三要素 : file表单项 post方式 multipart/from-data 服务端接收文件 : 用spring中的API : MultipartFile 要想文件名唯一 …

[极客大挑战 2019]Http 1

题目环境&#xff1a; 看起来挺花里胡哨的 F12查看源代码寻找隐藏文件 这是啥子呀&#xff0c;果然防不胜防 点击隐藏文件Secret.php 它不是来自这个地址的请求 报头&#xff1a;https://Sycsecret.buuoj.cn 需要抓包&#xff0c;在抓包前了解部分数据包参数 GET:到 Host:来自 …

Mysql my.cnf配置文件参数详解

Linux 操作系统中 MySQL 的配置文件是 my.cnf&#xff0c;一般会放在 /etc/my.cnf 或 /etc/mysql/my.cnf 目录下。 如果你使用 rpm 包安装 MySQL 找不到 my.cnf 文件&#xff0c;可参考如下&#xff1a; 第一步&#xff1a; 通过cd命令 cd /usr/share/mysql 来到这个目录&#…

ElementUI 自定义 Tree 树形控件背景

在 template 中 <div class"container"><el-tree :data"treeList" :props"defaultProps" accordion node-click"handleNodeClick" /> </div> 在 script 中 treeList: [{ id: "-1", label: "区域选…

由于flutter_app依赖于flutter_swiper>=0.0.2,不支持零安全,版本解决失败。

参考 dart3.0使用flutter_swiper报错记录 flutter_swiper package - All Versions从官网的信息可以看到 Dart3版本不兼容 最小兼容的Dart SDK版本需要2.0 Flutter SDK 版本列表Flutter SDK 版本列表 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 说明&#xff1a;因…

算法:Java构建二叉树并递归实现二叉树的前序、中序、后序遍历

先自定义一下二叉树的类&#xff1a; // Definition for a binary tree node. public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val val;this.left…

Python和SQLite游标处理多行数据

如果您需要处理多行数据&#xff0c;使用游标或其他适当的方法是更好的选择。以下是一些处理多行数据的方法&#xff1a; 使用游标&#xff1a;游标可以逐行处理查询结果&#xff0c;这对于大量数据或需要逐行处理的场景非常有用。以下是一个使用Python和SQLite的游标示例&…

对Java的多线程的理解

说说对Java线程的理解 下面是AI的回答 Java线程就是Java程序里面可以同时运行多个任务。Java提供了几种创建和管理线程的方式&#xff0c;其中一种是继承Thread类&#xff0c;另一种是实现Runnable接口或Callable接口。jdk5提供了线程池&#xff0c;可以更方便地创建、启动和终…

理解springboot那些过滤器与调用链、包装或封装、设计模式相关等命名规范,就可以读懂80%的springboot源代码,和其他Java框架代码

紧接上面《 理解springboot那些注册与回调、监控与统计等命名规范,就可以读懂70%的springboot源代码》、《 理解springboot那些约定俗成的框架类名、全局context等命名规范,就可以读懂一半springboot的源代码》2篇文章,此片将汇总springboot那些过滤器与调用链、包装或封装…

springboot面试题

Springboot核心注解是那几个&#xff1f;由那几个注解组成 启动类Application 上面的注解 SpringbootApplication 由一下三个注解组合 SpringbootConfiguration: 组合了Configuration注解&#xff0c;实现配置文件的功能 EnableSAutoConfiguration: 打开自动配置功能。 Compo…

【多线程】龟兔赛跑

package org.example;public class Race implements Runnable {//胜利者private static String winner;Overridepublic void run() {for(int i0;i<100;i){boolean flag gameOver(i);//如果flag>100,结束比赛if(flag){break;}System.out.println(Thread.currentThread().g…

Adobe After Effects 2024(Ae2024)在新版本中的升级有哪些?

After Effects 2024是Adobe公司推出的一款视频处理软件&#xff0c;它适用于从事设计和视频特技的机构&#xff0c;包括电视台、动画制作公司、个人后期制作工作室以及多媒体工作室。通过After Effects&#xff0c;用户可以高效且精确地创建无数种引人注目的动态图形和震撼人心…

DAY43 完全背包理论基础 + 518.零钱兑换II

完全背包 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&#xff08;也就是可以放入背包多次&#xff09;&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 完全背包和01背包问题唯一不同…