03:Heap代码的分析

Heap代码的分析

  • 1、内存对齐
  • 2、Heap_1.c文件代码分析
  • 3、Heap_2.c文件代码分析
  • 4、Heap_4.c文件代码分析
  • 5、Heap_5.c文件代码分析

1、内存对齐

内存对齐的作用是为了CPU更快的读取数据。对齐存储与不对齐存储的情况如下:
在这里插入图片描述计算机读取内存中的数据时是一组一组的读取的。尤其是与处理器的字长和内存总线的宽度相关。以下是几种常见情况:

32位系统:通常为4字节(32位),即一次读取4个字节的数据。
64位系统:通常为8字节(64位),即一次读取8个字节的数据。

在32位的系统中:

若不对齐存储数据,当CPU读取char数据和int数据时,第一次读取:从0x00~0x03,读取到12,20,30,40。然后将12取出来作为char类型的数据。第二次读取:从0x00 ~ 0x03,读取到12,20,30,40。然后将20,30,40取出来作为int类型的数据。第三次读取:从0x04 ~ 0x07,读取到50,然后加上第二次读取的数据,最后作为int类型的数据。

若对齐存储数据,当CPU读取char数据和int数据时,第一次读取:从0x00~0x03,读取到12。然后将12作为char类型的数据。第二次读取:从0x04 ~ 0x07,读取到20,30,40,50。然后将其作为int类型的数据。

综上:对齐存储数据是,当CPU去读取数据更快捷方便。

在计算机中数据的存储都是以内存对齐存储的。
实验代码如下:
①:基本类型变量存储情况

#include <stdio.h>char a = 10;
int b = 30;
long long c = 50;int main(void)
{printf("%p\n",&a);printf("%p\n",&b);printf("%p\n",&c);return 0;
}

0000000000403010
0000000000403014
0000000000403018

在这里插入图片描述

内存对齐:char(1字节对齐) 		类型的变量只能存放在被1整除的地址中:例如0x00,0x01,0x02,0x03........					//尾数为0,1,2,3的地址int(4字节对齐)			类型的变量只能存放在被4整除的地址中: 例如0x00,0x04,0x08,0x0C,0x10,0x14........		//尾数为0,4,8,C的地址long long(8字节对齐)	类型的变量只能存放在被8整除的地址中: 例如0x00,0x08,0x10,0x18,0x20,0x28,0x30........	//尾数为0,8的地址
#include <stdio.h>char a = 10;
long long b = 10;
char c = 10;	int main(void)
{printf("%p\n",&a);printf("%p\n",&b);printf("%p\n",&c);return 0;
}

0000000000403010
0000000000403018
0000000000403020

在这里插入图片描述
②:结构体变量存储情况

#include <stdio.h>struct Num{char a;int b;char c;	
};struct Num Node = {10,10,10}; 
char d = 10;
int main(void)
{printf("%p\n",&Node.a);printf("%p\n",&Node.b);printf("%p\n",&Node.c);printf("%p\n",&d);printf("结构体大小:%d\n",sizeof(Node));return 0;
}

0000000000403010
0000000000403014
0000000000403018
000000000040301C
结构体大小:12

在这里插入图片描述为什么结构体的大小不是9个字节喃?而是12个字节。因为结构体的大小为最大对齐数的正数倍。Node结构体的最大对齐数为int类型的4(即Node结构体是以4个字节对齐),所以为12个字节。

②:结构体嵌套存储情况

#include <stdio.h>struct Num1{char a;int b;char c;	
};struct Num2{char m;struct Num1 Node;//结构体嵌套char n;	
};
struct Num2 Number = {2,{5,7,8},1};
int main(void)
{printf("%p\n",&Number.m);printf("%p\n",&Number.Node.a);printf("%p\n",&Number.Node.b);printf("%p\n",&Number.Node.c);printf("%p\n",&Number.n);printf("结构体大小:%d\n",sizeof(Number));return 0;
}

0000000000403010
0000000000403014
0000000000403018
000000000040301C
0000000000403020
结构体大小:20

在这里插入图片描述
结构体Node是以4个字节对齐,则m与Node间隔中间添加3个空白字节,Number 也是以4个字节对齐,则n后面添加3个空白字节。所以Number为20个字节。

综上:需要定义的结构体占用存储空间最小,则定义时最好是(从小到大/从大到小)依次定义。

验证代码①如下:

#include <stdio.h>struct Num1{char a;int b;char c;	
};struct Num2{char m;//struct Num1 Node;char n;	struct Num1 Node;
};
struct Num2 Number = {2,1,{5,7,8}};
int main(void)
{printf("%p\n",&Number.m);printf("%p\n",&Number.n);printf("%p\n",&Number.Node.a);printf("%p\n",&Number.Node.b);printf("%p\n",&Number.Node.c);printf("结构体大小:%d\n",sizeof(Number));return 0;
}

0000000000403010
0000000000403014
0000000000403018
000000000040301C
0000000000403011
结构体大小:16

可见Number占用空间为16个字节,比之前的20个字节节省了4个字节。
验证代码②如下:

#include <stdio.h>struct Num{int b;char a;char c;	
};struct Num Node = {10,10,10}; 
int main(void)
{printf("%p\n",&Node.b);printf("%p\n",&Node.a);printf("%p\n",&Node.c);printf("结构体大小:%d\n",sizeof(Node));return 0;
}

0000000000403010
0000000000403014
0000000000403015
结构体大小:8

可见Node 占用空间为8个字节,比之前的12个字节节省了4个字节。

2、Heap_1.c文件代码分析

Heap.c里面实现分配堆空间的函数,即pvPortMalloc函数

heap_1.c文件的里面,只实现了pvPortMalloc函数,而未实现vPortFree函数,所以heap_1.c实现了只分配,不回收的功能。

在FreeRTOS的FreeRTOSConfig.h文件里面使用#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )宏来定义一个全局数组ucHeap的大小。如下图所示:

在这里插入图片描述

所以,FreeRTOS的堆空间都是在这个全局数组里面进行分配的。
heap_1.c文件的源码如下:

#define configADJUSTED_HEAP_SIZE    ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];static size_t xNextFreeByte = ( size_t ) 0;/*-----------------------------------------------------------*/void * pvPortMalloc( size_t xWantedSize )
{void * pvReturn = NULL;static uint8_t * pucAlignedHeap = NULL;#if ( portBYTE_ALIGNMENT != 1 ){if( xWantedSize & portBYTE_ALIGNMENT_MASK ){if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) > xWantedSize ){xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );}else{xWantedSize = 0;}}}#endif vTaskSuspendAll();{if( pucAlignedHeap == NULL ){pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) & ucHeap[ portBYTE_ALIGNMENT - 1 ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );}if( ( xWantedSize > 0 ) &&                                ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) ){pvReturn = pucAlignedHeap + xNextFreeByte;xNextFreeByte += xWantedSize;}traceMALLOC( pvReturn, xWantedSize );}( void ) xTaskResumeAll();#if ( configUSE_MALLOC_FAILED_HOOK == 1 ){if( pvReturn == NULL ){vApplicationMallocFailedHook();}}#endifreturn pvReturn;
}void vPortFree( void * pv )
{( void ) pv;configASSERT( pv == NULL );
}

在这里插入图片描述

3、Heap_2.c文件代码分析

4、Heap_4.c文件代码分析

5、Heap_5.c文件代码分析

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

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

相关文章

自动驾驶---苏箐对智驾产品的思考

1 前言 对于更高级别的自动驾驶&#xff0c;很多人都有不同的思考&#xff0c;方案也好&#xff0c;产品也罢。最近在圈内一位知名的自动驾驶专家苏箐发表了他自己对于自动驾驶未来的思考。 苏箐是地平线的副总裁兼首席架构师&#xff0c;同时也是高阶智能驾驶解决方案SuperDri…

Android BitmapShader简洁实现马赛克/高斯模糊(毛玻璃),Kotlin(三)

Android BitmapShader简洁实现马赛克/高斯模糊&#xff08;毛玻璃&#xff09;&#xff0c;Kotlin&#xff08;三&#xff09; 发现&#xff0c;如果把&#xff08;二&#xff09; Android BitmapShader简洁实现马赛克&#xff0c;Kotlin&#xff08;二&#xff09;-CSDN博客 …

【数据结构】 并查集 + 路径压缩与按秩合并 python

目录 前言模板朴素实现路径压缩按秩合并按树高为秩按节点数为秩 总结 前言 并查集的基本实现通常使用森林来表示不同的集合&#xff0c;每个集合用一棵树表示&#xff0c;树的每个节点有一个指向其父节点的指针。 如果一个节点是它自己的父节点&#xff0c;那么它就是该集合的代…

【深度学习入门_机器学习理论】K近邻法(KNN)

本部分主要为机器学习理论入门_K近邻法(KNN)&#xff0c;书籍参考 “ 统计学习方法&#xff08;第二版&#xff09;”。 学习目标&#xff1a; 了解k近邻算法的基本概念、原理、应用&#xff1b;熟悉k近邻算法重要影响要素&#xff1b;熟悉kd树原理与优化应用。 开始本算法之…

深入理解 SQL 中的子查询

文章目录 一、什么是子查询二、子查询的基本语法三、数据准备四、子查询的分类4.1 标量子查询4.2 单行子查询4.3 多行子查询4.4 关联子查询 五、子查询的应用场景5.1 子查询与 WHERE 子句5.2 子查询与 SELECT 子句5.3 子查询与 FROM 子句 六、性能优化与注意事项 本文将深入探讨…

Zookeeper入门部署(单点与集群)

本篇文章基于docker方式部署zookeeper集群&#xff0c;请先安装docker 目录 1. docker初期准备 2.启动zookeeper 2.1 单点部署 2.2 集群部署 3. Linux脚本实现快速切换启动关闭 1. docker初期准备 拉取zookeeper镜像 docker pull zookeeper:3.5.6 如果拉取时间过长&#xf…

【SpringBoot教程】Spring Boot + MySQL + HikariCP 连接池整合教程

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 在前面一篇文章中毛毛张介绍了SpringBoot中数据源与数据库连接池相关概念&#xff0c;今天毛毛张要分享的是关于SpringBoot整合HicariCP连接池相关知识点以及底层源码…

SCRM在企业私域流量与客户管理中的变革之路探索

内容概要 在当今数字化高速发展的时代&#xff0c;SCRM&#xff08;社交客户关系管理&#xff09;作为一种新的管理工具&#xff0c;正逐渐成为企业私域流量管理和客户关系维护的重要基石。它不仅仅是一种软件工具&#xff0c;更是一种整合客户数据和关系管理的全新思维方式。…

实战 | 域环境下通过anydesk进入生产网

视频教程在我主页简介或专栏里 目录&#xff1a; 前言 外网突破 资产扫描与常规漏洞 经典的MS17010漏洞利用&#xff1a; 网络通信设备弱口令&#xff1a; 安全防护设备集群&#xff1a; 域环境渗透 核心生产网渗透 总结 教程下载链接&#xff1a;zkanzz 话不多说&#x…

卡特兰数学习

1&#xff0c;概念 卡特兰数&#xff08;英语&#xff1a;Catalan number&#xff09;&#xff0c;又称卡塔兰数&#xff0c;明安图数。是组合数学中一种常出现于各种计数问题中的数列。它在不同的计数问题中频繁出现。 2&#xff0c;公式 卡特兰数的递推公式为&#xff1a;f(…

算法刷题Day28:BM66 最长公共子串

题目链接&#xff0c;点击跳转 题目描述&#xff1a; 解题思路&#xff1a; 方法一&#xff1a;暴力枚举 遍历str1的每个字符x&#xff0c;并在str2中寻找以相同元素x为起始的最长字符串。记录最长的公共子串及其长度。 代码实现&#xff1a; def LCS(self, str1: str, st…

Open FPV VTX开源之ardupilot双OSD配置摄像头

Open FPV VTX开源之ardupilot双OSD配置 1 源由2. 分析3. 配置4. 解决办法5. 参考资料 1 源由 鉴于笔者这台Mark4 Copter已经具备一定的历史&#xff0c;目前机载了两个FPV摄像头&#xff1a; 模拟摄像头数字摄像头(OpenIPC) 测试场景&#xff1a; 从稳定性的角度&#xff1…

【Super Tilemap Editor使用详解】(十六):高级主题:深入理解 Super Tilemap Editor

在本节中,我们将深入探讨 Super Tilemap Editor 的工作原理,特别是图块地图(Tilemap)的渲染机制以及如何优化性能。这些知识将帮助你更好地理解工具的内部机制,并在开发中做出更明智的决策。 一、图块地图与图块渲染 图块地图是 Super Tilemap Editor 的核心组件之一。它由…

01学习预热篇(D6_正式踏入JVM深入学习前的铺垫)

目录 学习前言 一、虚拟机的结构 1. Java虚拟机参数设置 2. java 堆 3. 出入栈 4. 局部变量表 1> 局部变量的剖析 2> 局部变量的回收 5. 操作数栈 1> 常量入栈指令 2> 局部变量值转载到栈中指令 3> 将栈顶值保存到局部变量中指令 6. 帧数据区 7. 栈…

Node.js下载安装及环境配置教程 (详细版)

Node.js&#xff1a;是一个基于 Chrome V8 引擎的 JavaScript 运行时&#xff0c;用于构建可扩展的网络应用程序。Node.js 使用事件驱动、非阻塞 I/O 模型&#xff0c;使其非常适合构建实时应用程序。 Node.js 提供了一种轻量、高效、可扩展的方式来构建网络应用程序&#xff0…

SimpleFOC STM32教程10|基于STM32F103+CubeMX,速度闭环控制(有电流环)

导言 SimpleFOC STM32教程09&#xff5c;基于STM32F103CubeMX&#xff0c;ADC采样相电流 如上图所示, 增加了电流环. 效果如下&#xff1a; 20250123-200906 RTT 如上图所示&#xff0c;三相占空比依然是马鞍波。当我用手去给电机施加阻力时&#xff0c;PID要维持目标转速&am…

【超详细】ELK实现日志采集(日志文件、springboot服务项目)进行实时日志采集上报

本文章介绍&#xff0c;Logstash进行自动采集服务器日志文件&#xff0c;并手把手教你如何在springboot项目中配置logstash进行日志自动上报与日志自定义格式输出给logstash。kibana如何进行配置索引模式&#xff0c;可以在kibana中看到采集到的日志 日志流程 logfile-> l…

DeepSeek-R1:强化学习驱动的推理模型

1月20日晚&#xff0c;DeepSeek正式发布了全新的推理模型DeepSeek-R1&#xff0c;引起了人工智能领域的广泛关注。该模型在数学、代码生成等高复杂度任务上表现出色&#xff0c;性能对标OpenAI的o1正式版。同时&#xff0c;DeepSeek宣布将DeepSeek-R1以及相关技术报告全面开源。…

李沐vscode配置+github管理+FFmpeg视频搬运+百度API添加翻译字幕

终端输入nvidia-smi查看cuda版本 我的是12.5&#xff0c;在网上没有找到12.5的torch&#xff0c;就安装12.1的。torch&#xff0c;torchvision&#xff0c;torchaudio版本以及python版本要对应 参考&#xff1a;https://blog.csdn.net/FengHanI/article/details/135116114 创…