Download presentation
Presentation is loading. Please wait.
Published byἝκτωρ Αθανασιάδης Modified 6年之前
1
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
《手把手教你学STM32》 主讲人 :正点原子团队 硬件平台:正点原子STM32开发板 版权所有:广州市星翼电子科技有限公司 淘宝店铺: 技术论坛: 开源电子网 公众平台:“正点原子” 官方网站: 联系电话: ddddd ALIENTEK 淘宝店铺: 技术论坛:
2
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
《手把手教你学STM32》 LWIP内存管理 适用平台 适用平台 STM32F1xx 开发板 (正点原子) STM32F4xx 开发板 (正点原子) STM32F4xx 开发板 (正点原子) ENC28J60 模块 (正点原子) ddddd 淘宝店铺: 技术论坛:
3
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
本视频重点参考资料 参考资料: 1,探索者STM32F407开发板 《STM32F4 LWIP开发手册》——LWIP无操作系统移植 2,以太网参考资料 《STM32F4xx中文参考手册》-第29章 以太网(ETH) 3,LWIP参考资料 《嵌入式网络那些事LWIP协议深度剖析与实战演练》 作者:朱升林 4,LAN8720参考资料 见光盘:硬件资料芯片资料 ① LAN820A.pdf 淘宝店铺: 技术论坛:
4
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
目录 内存管理简介 1 LWIP内存池 2 LWIP内存堆 3 淘宝店铺: 技术论坛:
5
LWIP内存管理 声明 本视频所有有关LWIP原理部分的内容均参考自《嵌入式网络那些事LWIP协议深度剖析与实战演练》,并且已经征得作者朱升林先生的同意。在此,感谢朱升林先生的支持。
6
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
1、内存管理简介 如果学过嵌入式操作系统的话就知道内存管理是非常重要的内容,任何一个操作系统都会提供内存管理的功能,虽然LWIP不是一个操作系统,但是LWIP需要处理大量的网络数据,所以也提供了内存管理。 学习C语言的时候我们肯定会学习malloc和free这两个函数的时候,这两个函数就是内存管理中重要的两个函数:内存申请和释放。 内存分配本质就是在一个大数组(内存堆)里面分配合适的空间,然后将这个空间的开始地址返回给调用者,内存分配中最重要的就是分配的时间效率! 内存碎片:内存堆在经过频繁的malloc和free之后可能会产生很多的碎小的不能使用的内存碎片。 淘宝店铺: 技术论坛:
7
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 LWIP中的内存池(POOL)分配策略简单,但是内存的分配、释放效率高,可以有效的防止内存碎片的产生。在内存的策略下用户只能申请固定大小的空间,内存池方法主要用于LWIP内核中固定数据结构的分配,比如UDP控制块,TCP控制块等。LWIP内核在初始化的时候已经为每个数据结构类型都初始化了一定数量的POOL,文件memp.c和memp.h就是内存池相关内容。 至于LWIP内核建立多少种POOL依赖于用户和系统配置,比如如果定义了宏LWIP_UDP为1,那么在编译时与UDP控制块数据结构相关的内存池POOL就会被建立(MEMP_UDP_PCB),如果定义了宏LWIP_TCP为1,编译时与TCP数据结构相关的内存池就会被建立(MEMP_TCP_PCB、MEMP_TCP_SEG)等等!每种类型的POOL大小都是固定的。 有6个与LWIP内存池有关的全局变量和数据结构:memp_t、memp_tab[]、memp_sizes[]、memp_num[]、memp_desc[]和memp_memory[]。 淘宝店铺: 技术论坛:
8
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 memp_t数据类型 memp_t为一个枚举类型变量,用来给每个POOL取个名字,或者说是编号。memp_t在文件memp.h文件中定义,定义如下: typedef enum { #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, #include "lwip/memp_std.h" MEMP_MAX } memp_t; 淘宝店铺: 技术论坛:
9
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 memp_t数据类型 memp_t的真实面目如下: typedef enum { MEMP_ RAW_PCB, MEMP_ UDP_PCB, MEMP_ TCP_PCB, MEMP_ TCP_PCB_LISTEN, MEMP_ TCP_SEG, MEMP_ REASSDATA, ……. MEMP_MAX } memp_t; 其中MEMP_MAX代表memp_t代表枚举类型中元素总个数,并不代表任何类型的POOL 淘宝店铺: 技术论坛:
10
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 memp_tab全局指针数组 memp_tab为一个全局指针数组,指向每类POOL的第一个POOL,memp_tab在文件memp.c文件中定义,定义如下: static struct memp *memp_tab[MEMP_MAX]; memp_sizes全局数组 memp_sizes为一个全局数组,用来记录每个POOL的大小,memp_sizes在文件memp.c文件中定义,定义如下: const u16_t memp_sizes[MEMP_MAX] = { #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size), #include "lwip/memp_std.h" }; 淘宝店铺: 技术论坛:
11
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 memp_sizes数据类型 memp_sizes的真实面目如下: const u16_t memp_sizes[MEMP_MAX] = { LWIP_MEM_ALIGN_SIZE(sizeof(struct raw_pcb)), LWIP_MEM_ALIGN_SIZE(sizeof(struct udp_pcb)), LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_pcb)), LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_pcb_listen)), LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_seg)), ……. } memp_sizes中保存了每种类型POOL的大小,这里的大小都是进行了内存对齐的。 淘宝店铺: 技术论坛:
12
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 memp_num[]全局数组 memp_num为一个全局数组,用来记录每类POOL中POOL的个数,memp_num在文件memp.c文件中定义,定义如下: const u16_t memp_num[MEMP_MAX] = { #define LWIP_MEMPOOL(name,num,size,desc) (num), #include "lwip/memp_std.h“ }; 淘宝店铺: 技术论坛:
13
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 memp_num数组 memp_num的真实面目如下: const u16_t memp_num[MEMP_MAX] = { MEMP_NUM_RAW_PCB, MEMP_NUM_UDP_PCB, MEMP_NUM_TCP_PCB, MEMP_NUM_TCP_PCB_LISTEN, MEMP_NUM_TCP_SEG …… }; 上面的MEMP_NUM_RAW_PCB、MEMP_NUM_UDP_PCB等等都是又用户定义的,用来记录对应的POOL的数量,用户可以在lwipopts.h文件中定义,LWIP在opt.h中已经配置了默认值。 淘宝店铺: 技术论坛:
14
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 memp_desc[]全局型指针数组 memp_desc为一个全局型指针数组,指向每类POOL的描述符 ,memp_desc在文件memp.c文件中定义,定义如下: static const char *memp_desc[MEMP_MAX] = { #define LWIP_MEMPOOL(name,num,size,desc) (desc), #include "lwip/memp_std.h" }; 淘宝店铺: 技术论坛:
15
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 memp_desc全局指针数组 memp_desc的真实面目如下: static const char *memp_desc[MEMP_MAX] = { ("RAW_PCB"), ("UDP_PCB"), ("TCP_PCB"), ("TCP_PCB_LISTEN"), ……. }; memp_desc中的每个元素指向了一个字符串,这些字符串在统计信息输出中可能用到。 淘宝店铺: 技术论坛:
16
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 memp_memory[]数组 memp_memory为一个数组,这个数组才是真正的内存池!!!这个数组 在文件memp.c文件中定义,定义如下: static u8_t memp_memory[MEM_ALIGNMENT - 1 #define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) #include "lwip/memp_std.h" ]; 淘宝店铺: 技术论坛:
17
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 memp_memory数组 memp_desc的真实面目如下: static u8_t memp_memory [ MEM_ALIGNMENT – 1 +((MEMP_NUM_RAW_PCB) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct raw_pcb)) )) +((MEMP_NUM_UDP_PCB) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct udp_pcb)) )) +((MEMP_NUM_TCP_PCB) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct tcp_pcb)) )) …….. ]; 其中MEMP_SIZE表示需要在每个POOL头部预留的空间,LWIP中在某些特殊场合使用该空间中的值来对POOL进行特殊处理,这里不使用该项功能,所以MEMP_SIZE为0,。如果使用到MEMP_SIZE的话也需要对这个大小进行内存对齐! 淘宝店铺: 技术论坛:
18
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存池 LWIP中与内存池管理相关的有3个函数: 函数 描述 memp_init() 内存池初始化 memp_malloc() 内存池分配 memp_free() 内存池释放 使用内存池分配内存的优点在于速度快,效率高,不会产生内存碎片,但是缺点在于只能分配各种固定大小的内存空间,LWIP必须实现知道用户要使用哪些类型的POOL,每种类型的POOL数量,然后根据这个需求建立内存池。 淘宝店铺: 技术论坛:
19
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP内存堆 LWIP还提供了另外一种内存策略—内存堆,使用内存堆策略就可以随便申请任意大小的内存了。但是这种方法效率和速度会有所下降。 使用内存堆策略的话用户申请的内存大小有最小限制,所申请的内存大小不能小于MIN_SIZE,LWIP默认的MIN_SIZE为12个字节。该值用户可以自行定义。使用内存堆策略,其有点事内存浪费小,比较简单,适合于小内存的管理,但是缺点就是如果频繁的进行动态内存申请和释放的话,可能会造成严重的内存碎片,如果碎片严重的话可能会导致内存分配失败! 内存堆策略下的内存空间是数组:ram_heap[]。与内存堆有关的函数有3个: mem_init() mem_malloc() mem_free() 淘宝店铺: 技术论坛:
20
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP其他内存策略 前面讲的内存池(POOL)和内存堆(HEAP)这两个内存策略都是LWIP默认的内存策略,LWIP内核中大量的使用了这两个策略,不过LWIP也给我们提供了其他可选的内存策略。 (1)、当定义宏MEM_LIBC_MALLOC为1,那么与内存堆相关的代码就不会被编译的,内存堆中的mem_malloc()和mem_free()就会被ANSI C编译器自带的malloc()和free()替代。 (2)、当定义宏MEMP_MEM_MALLOC为1,那么内存池文件memp.c就不会被编译。 (3)、当定义宏MEM_USE_POOLS定义为1,那么内存堆分配相关的函数及全局变量不会被编译,这个时候就用内存池分配方式来显示内存堆的的分配方式,因为内存池的分配策略效率很高。 淘宝店铺: 技术论坛:
21
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
2、LWIP其他内存策略 但是(3)中的方法使用起来比较麻烦,需要在lwipopts.h中定义宏MEM_USE_POOLS和MEM_USE_CUSTOM_POOLS都为1,还需要在另外一个头文件lwippools.h中开辟一些用于内存堆分配函数的内存池。 这种方法是典型的空间还时间! 淘宝店铺: 技术论坛:
22
淘宝店铺:http://eboard.taobao.com 技术论坛:www.openedv.com
谢谢您对“正点原子”团队的支持 硬件平台:正点原子STM32开发板 版权所有:广州市星翼电子科技有限公司 淘宝店铺: 技术论坛: 淘宝店铺: 技术论坛:
Similar presentations