一文解析LWIP内存占用与裁剪 您所在的位置:网站首页 lwip的tcp如何提速 一文解析LWIP内存占用与裁剪

一文解析LWIP内存占用与裁剪

2024-07-09 08:42| 来源: 网络整理| 查看: 265

LWIP内存占用与裁剪

工具链:GCC

LWIP版本:2.0.2 默认配置

静态内存总体分布

网络相关内存占用主要分为三个部分,其中LWIP内存池占主要部分

DNS解析

LWIP内存池

RTT相关

DNS占用

DNS的内存占用在整个协议栈中的比重不大,仅1k左右。

DNS tab数组占用内存较多,如果应用中同时进行dns解析的场景较少,可适当较少DNS tab数量。可设置DNS_TABLE_SIZE=2。

DNS_MAX_NAME_LENGTH表示能够解析最大的DNS名字长度

MEMPOOL内存占用

LWIP内存占用主要在MEMPOOL这一块。通过提前开辟静态数组,来提高LWIP分配各种描述符内存的速度。静态内存总共分配42715字节,41K。

其中各种描述符分配了大约12202字节数据,静态内存池分配了25731字节数据。

描述符中 PBUF和ARP_QUEUE占用内存较多,静态分配了4510字节内存,这两个描述符可根据具体情况作出相应的调整

除去PBUF和ARP_QUEUE这两个描述符,其他描述符占用7692字节内存。

LWIP静态内存池占用大量内存,且使用较少,PBUF与ARP_QUEUE占用一部分内存,可做适当裁剪,通信相关的描述符,占用较少内存,7K左右。

单个大小 = (大小 + 1 - 4) / 数量

RTT相关占用

RTT静态内存总共占用2464字节,主要是用于启动rx,rx线程。当没有使用到这两个线程的时候,可以移除。

动态内存分配

初始化分配

系统启动时,会动态创建一个tcpip线程,需要消耗1172字节内存

会为tcpip线程创建一个邮箱,需要消耗80字节内存

会为tcpip线程创建一个互斥量,需要消耗36字节内存

创建连接分配

建立一个连接需要创建一个fd,消耗32字节内存

需要创建一个邮箱,消耗88字节内存

需要创建一个信号量,消耗32字节内存

还需要创建socket,netconn,pcb描述符等,这些占用静态内存

数据通信分配

发送数据时,需要动态分配pbuf缓存数据

接收数据时,需要动态分配pbuf缓存数据

发送TCP协议数据,需要TCP_SEG描述符,一包数据可能会占用多个TCP_SEG描述符

接收tcp协议数据,需要TCPIP_MSG_INPKT描述符

各个描述符的作用

PCB描述符

PCB描述符是用来管理连接协议的,不同的连接协议PCB不相同。PCB描述符有RAW,UDP,TCP,TCP_LISTEN这四种。

RAM描述符用来管理原始数据,直接提供IP报文的访问

UDP描述符用来管理UDP协议数据。

TCP描述符用来管理TCP协议通信数据

TCP_LISTEN描述符用来管理TCP侦听数据

NETCONN描述符

NETCONN描述符是用来管理一个连接,该连接类型可是RAW,UDP,TCP,TCP_LISTEN这四种。

收发数据描述符

收发数据需要描述符的,仅仅是TCP协议。

TCP发送数据时,需要将tcp报文打包,使用TCP_SEG描述符进行管理。

TCP接收数据时,需要将PBUF转换成TCP报文,然后使用TCPIP_MSG_INPKT描述符管理。

其他描述符

ARP_QUEUE,管理ARP数据包

IGMP_GROUP,多播,组播包管理

PBUF,只分配PBUF头部

PBUF_POOL,静态内存池

NETBUF

NETDB

TCPIP_MSG_API

NETDB

静态内存裁剪与影响

lwip最先应该裁剪静态内存池,耗得的内存最多

其次裁剪TCPIP_MSG_INPKT,PBUF等使用较少的描述符

在次裁剪RAW_PCB,UDP_PCB等东西

最后裁剪TCP_SEG,这个值与RT_LWIP_TCP_SND_BUF缓冲区有关,1k的缓冲区大约需要5个seg

发送窗口的大小不易过大,也不宜过小,更具网卡的性能做调整。网卡性能差,则窗口应该小,性能好则窗口大,相应的其他值也应该调大。

初步裁减

裁剪:静态内存占用最多的是内存池,默认配置内存池占用大约24k作用内存,LWIP内核中没有使用这一片内存,如果应用中没有使用这块内存,可以减少这一片内存 RT_LWIP_PBUF_NUM = 2 。可以减少20k的内存。

影响:静态内存池的减少并不会影响LWIP内核的效率,但可能对应用有影响。应用中如果使用了静态内存池,可能会导致内存分配失败。

均衡裁剪

裁剪:在描述符表中,PBUF描述符与ARP_QUEUE描述符占用内存较多,且使用不是特别频繁,可根据实际情况,减少这两种描述符的数据MEMP_NUM_PBUF MEMP_NUM_ARP_QUEUE。如果数量各减少一半,可以减少2k内存

影响:PBUF在LWIP内核中有少数地方在使用,减少PBUF数量可能导致LWIP运行不稳定。

影响:ARP_QUEUE是用来处理ARP请求的,减少ARP_QUEUE可能导致ARP请求失败,导致通信不成功。

极端裁剪

裁剪:可以根据应用情况,合理减少TCP_SEG描述符的数量。实际使用中,如果没有很多个TCP连接,且数据通信频繁或数据量大,可能巅峰时刻也用不完这种描述符。适当调整RT_LWIP_TCP_SEG_NUM的值达到节约内存的目的。如果数量减少一半,可以减少1k内存

裁剪:可以根据应用情况,合理减少PCB描述符及NETCONN的数量。

影响:不建议这种裁剪,除非极端缺少内存,而且裁剪也省不了多少内存,顶天2k,而且可能导致出现乱七八糟的问题。

其他

这部分不涉及内存裁剪相关的内容,介绍下RT_LWIP_TCP_SND_BUF RT_LWIP_TCP_WND这两个参数

RT_LWIP_TCP_SND_BUF:TCP发送缓冲区大小。首先这个缓冲区不会分配实际的内存。

RT_LWIP_TCP_WND:TCP发送窗口大小,当网络性能较弱时,应该适当调小发送窗口大小。

ifconfig参数的作用

RT_LWIP_UDP 使能UDP功能

RT_LWIP_TCP 使能TCP功能

RT_LWIP_RAW 使能RAM功能

RT_MEMP_NUM_NETCONN 8 最大连接数量

RT_LWIP_PBUF_NUM 16 静态内存池数量

RT_LWIP_RAW_PCB_NUM 4 RAW_PCB描述符数量

RT_LWIP_UDP_PCB_NUM 4 UDP_PCB描述符数量

RT_LWIP_TCP_PCB_NUM 4 TCP_PCB描述符数量

RT_LWIP_TCP_SEG_NUM 40 TCP发送数据描述符数量

RT_LWIP_TCP_SND_BUF 8196 缓存区大小

RT_LWIP_TCP_WND 2048 窗口大小

RT_LWIP_TCPTHREAD_PRIORITY 10 TCPIP线程优先级

RT_LWIP_TCPTHREAD_MBOX_SIZE 8 邮箱数据,同一时间能够接收的pbuf包

RT_LWIP_TCPTHREAD_STACKSIZE 1024 TCPIP线程栈大小

RT_LWIP_ETHTHREAD_PRIORITY 12 rx/tx发送线程优先级

RT_LWIP_ETHTHREAD_STACKSIZE 1024 rx/tx栈大小

RT_LWIP_ETHTHREAD_MBOX_SIZE 8 rx/tx邮箱数量

附录

各描述符大小

单个大小计算=(大小+1-4)/数量

PBUF_POOL 单个大小 1608

打印的原始数据如下,第一列数字是sizeof(memp_memory_RAW_PCB_base)描述符总共占的内存,第二列是实际使用的内存(总内存 + 1 - 4)

memp_memory_RAW_PCB_base 75 72

memp_memory_UDP_PCB_base 155 152

memp_memory_TCP_PCB_base 835 832

memp_memory_TCP_PCB_LISTEN_base 611 608

memp_memory_TCP_SEG_base 1803 1800

memp_memory_NETBUF_base 123 120

memp_memory_NETCONN_base 867 864

memp_memory_TCPIP_MSG_API_base 483 480

memp_memory_TCPIP_MSG_INPKT_base 483 480

memp_memory_ARP_QUEUE_base 1563 1560

memp_memory_SYS_TIMEOUT_base 303 300

memp_memory_NETDB_base 355 352

memp_memory_PBUF_base 739 736

memp_memory_PBUF_POOL_base 12867 12864

各SIZEOF大小

管理一个描述符所占大小

例如raw_pcb,其他的也是这样子计算的。

x = (((sizeof(struct memp)) + 4 - 1U) & ~(4 -1U)) + (((16) + 4 - 1U) & ~(4 -1U))

y = ((((sizeof(struct raw_pcb)) + 4 - 1U) & ~(4 -1U)) + (((16) + 4 - 1U) & ~(4 -1U)))

大小 = (x + y) * 数量

所占空间 = 大小 + 4 - 1U

创建一个连接需要的内存

socket = sizeof(struct lwip_sock)(32) + fd(32) + mb_create(88) + sem_create(32) = 184

netconn = 104

建立tcp客户端连接 = socket + netconn + tcp_pcb(204) = 492

建立tcp服务端连接 = socket + netconn + tcp_pcb_listen(72) = 360

tcp客户端通信 = tcp客户端连接 + 5 * TCP_SEG(60) = 792

tcp服务端通信 = tcp服务端连接 + netconn(104) + tcp_pcb(204) + 2 * tcpip_msg_inpkt(60) = 824

这里只统计了固定内存,或许还有遗漏。

通信过程中各种malloc和free的内存没有统计。LWIP会将发送的数据cp一遍,如发送4k数据,则至少malloc 4k内存拷贝数据,等数据确认发送完毕,则释放内存。

创建一个socket,fd分配的内存,严格来说应该不属于lwip这边的。

LWIP各选项描述

名字 默认值 描述

LWIP_SNMP 0    SNMP协议启用

SNMP_CONCURRENT_REQUESTS 1 SNMP当前允许请求数量

SNMP_TRAP_DESTINATIONS 1 SNMP trap目的地址数目

SNMP_PRIVATE_MIB 1     SNMP 私有节点设置允许

SNMP_SAFE_REQUESTS 1 仅回复SNMP安全请求

SYS_LIGHTWEIGHT_PROT 1 临界中断保护开关(多任务模式下开启)

NO_SYS 0 LWIP独立运行或者基于操作系统,为0则基于操作系统

MEM_LIBC_MALLOC 0 采用LWIP自带函数分配动态内存

MEM_LIBC_MALLOC 0 内存池不通过内存堆来分配

MEM_ALIGNMENT 4 字节对齐(和CPU的位数有关,32位设置为4)

MEM_SIZE 8*1024       堆内存大小,用于发送数据

MEMP_SANITY_CHECK 0 mem_free调用后检查链表是否有循环 by zc

MEMP_OVERFLOW_CHECK 0 lwip堆内存溢出检查

MEM_USE_POOLS 0 内存堆不通过内存池分配

MEM_USE_POOLS_TRY_BIGGER_POOL 0   申请内存失败不选择大内存池

MEMP_USE_CUSTOM_POOLS 0 同上

MEMP_NUM_PBUF 60    来自memp的PBUF_ROM(ROM内存池)和PBUF_REF(RAM内存池)数目最大总和

MEMP_NUM_RAW_PCB 4    RAW连接的PCB数目(需要LWIP RAW有效)

MEMP_NUM_UDP_PCB 4 能够同时连接的UDP的PCB数目

MEMP_NUM_TCP_PCB 4 能够同时连接的TCP的PCB数目

MEMP_NUM_TCP_PCB_LISTEN 1 能够同时监听的TCP的PCB数目

MEMP_NUM_TCP_SEG 40     能够同时在队列里的TCP的PCB数目

MEMP_NUM_REASSDATA 8 最大同时等待重装的IP包数目,是整个IP包,不是IP分片

MEMP_NUM_ARP_QUEUE 30 最大等待回复ARP请求的数目(ARP_QUEUEING有效)

MEMP_NUM_IGMP_GROUP 8 多播组同时接收数据的最大成员数目(LWIP_IGMP有效)

MEMP_NUM_SYS_TIMEOUT 20 能够同时激活的超时连接数目

MEMP_NUM_NETBUF 10 netbufs结构的数目

MEMP_NUM_NETCONN 16 netconns结构的数目

MEMP_NUM_TCPIP_MSG_API 40 tcpip_msg结构的最大数目,用于callback和API的通讯 by zc

MEMP_NUM_TCPIP_MSG_INPKT 40 tcpip_msg接受数据包结构的最大数目 by zc

PBUF_POOL_SIZE 48 内存池数量(小内存减小该选项可大大减小内存占用)

LWIP_ARP 1 ARP协议允许

ARP_TABLE_SIZE 10     ARP维护的表项大小

ARP_QUEUEING 1     硬件地址解析时,将发送数据包计入队列

ETHARP_TRUST_IP_MAC 1     所有IP数据包都会直接引起ARP table的更新,为0则非表项内IP-MAC关系会引起ARP请求

ETHARP_SUPPORT_VLAN 0     非虚拟局域网,为1则仅虚拟局域网通讯有效

IP_FORWARD 0 不允许不匹配数据包转发,多接口时为1

IP_OPTIONS_ALLOWED 1 带IP选项数据包允许 为0则丢弃所有IP数据包

IP_REASSEMBLY 1 允许接收IP包分片包(为0不允许,不能够接收大于MTU的包)

IP_FRAG 1 允许发送IP包分片包

IP_REASS_MAXAGE 3 允许接收的最大分段数

IP_REASS_MAX_PBUFS 10 最大允许存在的IP分片包占用的内存池个数

IP_FRAG_USES_STATIC_BUF 1 IP分片使用静态缓冲区

IP_FRAG_MAX_MTU 1500 IP分片最大缓冲数量

IP_DEFAULT_TTL 255 IP数据包最大经历设备数目

IP_SOF_BROADCAST 0 IP发送广播包过滤

IP_SOF_BROADCAST_RECV 0 IP接收广播包过滤

LWIP_ICMP 1 开启ping包接收/发送

ICMP_TTL (IP_DEFAULT_TTL) ping包最大经历设备数目

LWIP_BROADCAST_PING 0 不回复广播ping包

LWIP_MULTICAST_PING 0 不回复多播ping包

LWIP_RAW 0 无操作系统基于回调函数驱动

RAW_TTL (IP_DEFAULT_TTL) 应用层数据传输次数(基于IP层的TTL)

LWIP_DHCP 0 动态主机协议配置(为1时)

LWIP_AUTOIP 0 动态主机IP地址配置(为1时)

LWIP_DHCP_AUTOIP_COOP 0 允许上述两种配置同时存在于1个接口(为1时)

LWIP_DHCP_AUTOIP_COOP_TRIES 9 DHCP分配允许失败次数,失败则使用AUTOUP

LWIP_IGMP 0 LWIP组管理协议

LWIP_DNS 0 域名服务器模块(依托UDP协议)

DNS_TABLE_SIZE 4 域名服务器维护的最大入口数目

DNS_MAX_NAME_LENGTH 256 域名服务器主机地址最大长度

DNS_MAX_SERVERS 2 域名服务器最大服务数目

DNS_DOES_NAME_CHECK 1 查询域名服务器时检测地址名

DNS_USES_STATIC_BUF 1 域名服务器使用静态地址

DNS_MSG_SIZE 512 域名服务器接收最大通讯数据长度

DNS_LOCAL_HOSTLIST 0 在本地维护域名服务器主机-地址表(为1时)

DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 主机-地址表实时更新(为1时)

LWIP_UDP 1 启用UDP协议(snmp协议基于此)

LWIP_UDPLITE 1 UDP协议启用精简版

UDP_TTL (IP_DEFAULT_TTL) UDP数据包传输次数

LWIP_NETBUF_RECVINFO 0 接收到的数据包除首个外其它不附加目的地址和端口

LWIP_TCP 1 启用TCP协议(http协议基于此)

TCP_TTL (IP_DEFAULT_TTL) TCP数据包传输次数

TCP_WND 4*TCP_MSS tcp窗口大小

TCP_MAXRTX 12 最大允许重传TCP数据包数目

TCP_SYNMAXRTX 6 最大允许重传SYN连接包数目

TCP_QUEUE_OOSEQ (LWIP_TCP) TCP接收队列外数据块排序

TCP_MSS 1460 tcp报文最大分段长度

TCP_CALCULATE_EFF_SEND_MSS 1 tcp预计发送的分段长度,为1则根据窗口大小分配

TCP_SND_BUF (8*TCP_MSS) TCP发送缓冲区

TCP_SND_QUEUELEN (4*(TCP_SND_BUF/TCP_MSS)) TCP发送队列长度

TCP_SNDLOWAT (TCP_SND_BUF/4) TCP可发送数据长度

TCP_LISTEN_BACKLOG 1 TCP多连接允许

TCP_DEFAULT_LISTEN_BACKLOG 0xff TCP连接和半连接的总数

LWIP_TCP_TIMESTAMPS 0 TCP时间戳选项

TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4) TCP窗口更新阈值

TCP_MSL 10000UL TCP连接存在时间 单位ms

TCP_FIN_WAIT_TIMEOUT 20000UL FIN等到ACK应答时间 单位ms

TCP_TMR_INTERVAL 20 TCP定时器计数间隔 20ms

PBUF_LINK_HLEN 14 为处理以太网头申请的包长度(本地MAC地址+远端MAC地址+协议类型)6+6+2

PBUF_POOL_BUFSIZE 256 单个内存池长度,要考虑到4字节对齐和最佳大小

ETH_PAD_SIZE 0 以太网填充长度,stm32设置为0 根据发送包判断

LWIP_TCPIP_CORE_LOCKING 0

LWIP_NETCONN 1 应用层使用NETCONN相关函数

LWIP_SOCKET 0 关闭SOCKET通讯

LWIP_COMPAT_SOCKETS 1

LWIP_POSIX_SOCKETS_IO_NAMES 1

LWIP_SO_RCVTIMEO 0 conn->acceptmbox/recvmbox接收有超时限制,超时后自动断开连接

LWIP_SO_RCVBUF 0

SO_REUSE 0

LWIP_STATS 0 LWIP统计选项

CHECKSUM_GEN_IP 1 IP校验和生成

CHECKSUM_GEN_UDP 1 UDP校验和生成

CHECKSUM_GEN_TCP 1 TCP校验和生成

CHECKSUM_CHECK_IP 1 IP校验和校验

CHECKSUM_CHECK_UDP 1 UDP校验和校验

CHECKSUM_CHECK_TCP 1 TCP校验和校验

LWIP_TCP_KEEPALIVE 1 tcp保活定时器

TCP_KEEPIDLE_DEFAULT 60000 保活时间 60s

TCP_KEEPINTVL_DEFAULT 10000 保活探测 10s

TCP_KEEPCNT_DEFAULT 9U

DEBUG_OPTIONS 0 调试代码

原作者:还没想好



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有