文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

聊一聊Lwip内存管理策略

2024-12-03 06:57

关注

至于LWIP内核建立多少种POOL依赖于用户和系统配置,比如如果定义了宏LWIP_UDP为1,那么在编译时与UDP控制块数据结构相关的内存池POOL就会被建立(MEMP_UDP_PCB),如果定义了宏LWIP_TCP为1,编译时与TCP数据结构相关的内存池就会被建立(MEMP_TCP_PCB、MEMP_TCP_SEG)等等!每种类型的POOL大小都是固定的。用户可以在lwipopts.h文件中定义,LWIP在opt.h中已经配置了默认值。

有6个与LWIP内存池有关的全局变量和数据结构:memp_t、memp_tab[]、memp_sizes[]、memp_num[]、memp_desc[]和memp_memory[]。

1.1、memp_t数据类型

memp_t为一个枚举类型变量,用来给每个POOL取个名字,或者说是编号。memp_t在文件memp.h文件中定义,定义如下:

  1. #define LWIP_MEMPOOL(name,num,size,desc)  MEMP_##name

这句代码意思是:

遇到LWIP_MEMPOOL(name,num,size,desc) 换成MEMP_##name

例如:在memp_std.h的34行

  1. LWIP_MEMPOOL(RAW_PCB,        MEMP_NUM_RAW_PCB,         sizeof(structraw_pcb),        "RAW_PCB"

变成了

 

  1. MEMP_RAW_PCB 

所以memp_t编译之后如下:

  1. typedef enum 
  2.     MEMP_ RAW_PCB, 
  3.     MEMP_ UDP_PCB, 
  4.     MEMP_ TCP_PCB, 
  5.     MEMP_ TCP_PCB_LISTEN, 
  6.     MEMP_ TCP_SEG, 
  7.     MEMP_ REASSDATA, 
  8.      ……. 
  9.     MEMP_MAX 
  10. } memp_t; 

其中MEMP_MAX代表memp_t代表枚举类型中元素总个数(C语言基础知识),并不代表任何类型的POOL

1.2、memp_tab全局指针数组

memp_tab为一个全局指针数组,指向每类POOL的第一个POOL,memp_tab在文件memp.c文件中定义,定义如下:

1.3、memp_sizes全局数组

memp_sizes为一个全局数组,用来记录每个POOL的大小,memp_sizes在文件memp.c文件中定义,定义如下:

编译之后

  1. const u16_t memp_sizes[MEMP_MAX] = 
  2.     LWIP_MEM_ALIGN_SIZE(sizeof(struct raw_pcb)), 
  3.     LWIP_MEM_ALIGN_SIZE(sizeof(struct udp_pcb)), 
  4.     LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_pcb)), 
  5.     LWIP_MEM_ALIGN_SIZE(sizeof(structtcp_pcb_listen)), 
  6.     LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_seg)), 
  7.     ……. 

memp_sizes中保存了每种类型POOL的大小,这里的大小都是进行了内存对齐的。

这个宏定义,MEM_ALIGNMENT为4,也就是4字节对齐。

分析这个宏定义,也就说,当MEM_ALIGNMENT为4时,传入的size为3时,变为4

申请3个字节,实际申请4个字节

申请6个字节,实际申请8个字节

申请18个字节,实际申请20个字节

1.4、 memp_num[]全局数组

memp_num为一个全局数组,用来记录每类POOL中POOL的个数,memp_num在文件memp.c文件中定义,定义如下:

编译之后

  1. const u16_t memp_num[MEMP_MAX] = 
  2.     (MEMP_NUM_RAW_PCB), 
  3.     (MEMP_NUM_UDP_PCB), 
  4.     (MEMP_NUM_TCP_PCB), 
  5.     (MEMP_NUM_TCP_PCB_LISTEN), 
  6.     (MEMP_NUM_TCP_SEG), 
  7.     …… 
  8. }; 

上面的MEMP_NUM_RAW_PCB、MEMP_NUM_UDP_PCB等等都是由用户定义的,用来记录对应的POOL的数量,用户可以在lwipopts.h文件中定义,LWIP在opt.h中已经配置了默认值。

1.5、memp_desc[]全局型指针数组

memp_desc为一个全局型指针数组,指向每类POOL的描述符,memp_desc在文件memp.c文件中定义,定义如下:

编译之后

  1. static const char *memp_desc[MEMP_MAX] = 
  2.    ("RAW_PCB"), 
  3.    ("UDP_PCB"), 
  4.    ("TCP_PCB"), 
  5.    ("TCP_PCB_LISTEN"), 
  6.    ("TCP_PCB_LISTEN"), 
  7.    ……. 
  8. }; 

memp_desc中的每个元素指向了一个字符串,这些字符串在统计信息输出中可能用到。

1.6、memp_memory[]数组

memp_memory为一个数组,这个数组才是真正的内存池!!!这个数组在文件memp.c文件中定义,定义如下:

编译之后

  1. static u8_t memp_memory 
  2.    MEM_ALIGNMENT – 1 
  3.    +((MEMP_NUM_RAW_PCB) * (MEMP_SIZE + 
  4.      MEMP_ALIGN_SIZE(sizeof(struct raw_pcb)) )) 
  5.    +((MEMP_NUM_UDP_PCB) * (MEMP_SIZE + 
  6.     MEMP_ALIGN_SIZE(sizeof(struct udp_pcb)) )) 
  7.    +((MEMP_NUM_TCP_PCB) * (MEMP_SIZE + 
  8.     MEMP_ALIGN_SIZE(sizeof(struct tcp_pcb)) )) 
  9.    …….. 
  10. ]; 

其中MEMP_SIZE表示需要在每个POOL头部预留的空间,LWIP中在某些特殊场合使用该空间中的值来对POOL进行特殊处理,这里不使用该项功能,所以MEMP_SIZE为0,。如果使用到MEMP_SIZE的话也需要对这个大小进行内存对齐!

1.7、与内存池管理相关的函数:

使用内存池分配内存的优点在于速度快,效率高,不会产生内存碎片,但是缺点在于只能分配各种固定大小的内存空间,LWIP必须实现知道用户要使用哪些类型的POOL,每种类型的POOL数量,然后根据这个需求建立内存池。

02内存堆

LWIP还提供了另外一种内存策略—内存堆,使用内存堆策略就可以随便申请任意大小的内存了。但是这种方法效率和速度会有所下降。

使用内存堆策略的话用户申请的内存大小有最小限制,所申请的内存大小不能小于MIN_SIZE,LWIP默认的MIN_SIZE为12个字节,在mem.c文件中。该值用户可以自行定义。

使用内存堆策略,其有点事内存浪费小,比较简单,适合于小内存的管理,但是缺点就是如果频繁的进行动态内存申请和释放的话,可能会造成严重的内存碎片,如果碎片严重的话可能会导致内存分配失败!

内存堆策略下的内存空间是数组:ram_heap[]。在mem.c文件中。

与内存堆有关的函数有3个:

  1. mem_init() 
  2. mem_malloc() 
  3. mem_free() 

03其他内存策略

前面讲的内存池(POOL)和内存堆(HEAP)这两个内存策略都是LWIP默认的内存策略,LWIP内核中大量的使用了这两个策略,不过LWIP也给我们提供了其他可选的内存策略。

(1)、当定义宏MEM_LIBC_MALLOC为1,那么与内存堆相关的代码就不会被编译的,内存堆中的mem_malloc()和mem_free()就会被ANSIC编译器自带的malloc()和free()替代。

(2)、当定义宏MEMP_MEM_MALLOC为1,那么内存池文件memp.c就不会被编译。

(3)、当定义宏MEM_USE_POOLS定义为1,那么内存堆分配相关的函数及全局变量不会被编译,这个时候就用内存池分配方式来实现内存堆的的分配方式,因为内存池的分配策略效率很高。

但是(3)中的方法使用起来比较麻烦,需要在lwipopts.h中定义宏MEM_USE_POOLS和MEM_USE_CUSTOM_POOLS都为1,还需要在另外一个头文件lwippools.h中开辟一些用于内存堆分配函数的内存池。

 

来源: 知晓编程内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯