说明:因为来源做者也是转载的,且未说明出处,本文真正做者未知,若有侵权,请联系杰杰删除,欢迎关注个人公众号——干货不断html
SYS_LIGHTWEIGHT_PROT 平台锁,保护关键区域内缓存的分配与释放 NO_SYS --- 是否带操做系统, =1时带,=0时,不带 MEMCPY(dst,src,len) --- 内存拷贝 若你但愿本身写拷贝函数则可替换 SMEMCPY(dst,src,len) ---内存拷贝 若你但愿本身写拷贝函数则可替换 MEM_LIBC_MALLOC --- 内存函数库的使用,=1时使用c库 =0时使用本身的库 MEMP_MEM_MALLOC --- = 1时,使用mem_malloc/mem_free代替分配池 MEM_ALIGNMENT --- 字节对齐 = 1时应该是2字节对齐 MEM_SIZE --- 堆内存大小 若发送内容不少,则应设置很高 MEMP_OVERFLOW_CHECK --- 溢出保护为0时关闭,能够有1和2,2比较慢 MEMP_SANITY_CHECK --- 链检查,每次free后检查列表是否有循环 MEM_USE_POOLS --- 自定义内存池 MEM_USE_POOLS_TRY_BIGGER_POOL--- 内存池增大,增长系统可靠性 MEMP_USE_CUSTOM_POOLS --- 使用自定义内存池与lwippools.h有关 LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT --- 其余上下文释放内存 MEMP_NUM_PBUF --- RAW协议控制块数量 MEMP_NUM_UDP_PCB --- UDP协议控制块的数量 MEMP_NUM_TCP_PCB --- TCP协议控制块的数量 MEMP_NUM_TCP_PCB_LISTEN ---TCP监听链接数 MEMP_NUM_TCP_SEG --- TCP排队数量 MEMP_NUM_REASSDATA --- IP数据包排队数量 MEMP_NUM_ARP_QUEUE --- arp队列数 MEMP_NUM_IGMP_GROUP --- 组播网络接口数 MEMP_NUM_SYS_TIMEOUT --- 系统超时设置 MEMP_NUM_NETBUF --- netbuf结构数 MEMP_NUM_NETCONN --- netconn结构数 MEMP_NUM_TCPIP_MSG_API --- tcpip消息数 MEMP_NUM_TCPIP_MSG_INPKT --- tcpip数据包相关设置 PBUF_POOL_SIZE --- pbuf池大小 LWIP_ARP ---功能开启关闭 ARP_TABLE_SIZE --- ip地址缓冲对数量 ARP_QUEUEING --- arp队列 ETHARP_TRUST_IP_MAC ---arp ip mac先关 IP_FORWARD --- ip包转发 IP_OPTIONS_ALLOWED ---ip选项容许 IP_REASSEMBLY --- IP断点续传 IP_FRAG --- IP断点发送 IP_REASS_MAXAGE --- 分段数据包最大时间 IP_REASS_MAX_PBUFS --- 分段组装条数 IP_FRAG_USES_STATIC_BUF --- 使能静态缓冲区 IP_FRAG_MAX_MTU ---IP最大缓冲数量 IP_DEFAULT_TTL --- IP最大ttl时间 IP_SOF_BROADCAST --- ip sof广播 IP_SOF_BROADCAST_RECV --- spf广播过滤 LWIP_ICMP --- ICMP使能 ICMP_TTL --- ICMP最大ttl时间 LWIP_BROADCAST_PING --- 是否响应广播ping LWIP_MULTICAST_PING --- 是否响应组播ping LWIP_RAW ---raw协议使能 RAW_TTL --- raw ttl时间 LWIP_DHCP --- DHCP使能 DHCP_DOES_ARP_CHECK --- arp地址检查 LWIP_AUTOIP --- 自动ip使能 LWIP_DHCP_AUTOIP_COOP --- dhcp 自动ip接口 WIP_DHCP_AUTOIP_COOP_TRIES --- dhcp发现数 LWIP_SNMP --- snmp使能 SNMP_CONCURRENT_REQUESTS ---snmp并发数 SNMP_TRAP_DESTINATIONS --- snmp 陷阱相关 SNMP_PRIVATE_MIB --- snmp 私用mib SNMP_SAFE_REQUESTS --- snmp安全相关 LWIP_IGMP --- IGMP设置 LWIP_DNS --- DNS使能 DNS_TABLE_SIZE --- dns最大记录数 DNS_MAX_NAME_LENGTH --- dns主机名最大长度 DNS_MAX_SERVERS --- 最大dns服务数 DNS_DOES_NAME_CHECK --- dns 响应校验 DNS_USES_STATIC_BUF --- dns本地缓存数 DNS_MSG_SIZE --- dns消息大小 DNS_LOCAL_HOSTLIST --- dns 主机列表 DNS_LOCAL_HOSTLIST_IS_DYNAMIC --- dns动态列表 LWIP_UDP --- udp使能 LWIP_UDPLITE --- udp数据报 UDP_TTL --- udp ttl时间 LWIP_TCP --- TCP 使能 TCP_TTL --- TCP TTL时间 TCP_WND --- TCP窗口长度 TCP_MAXRTX --- TCP最大重传次数 TCP_SYNMAXRTX --- TCP syn段最大重传次数 TCP_QUEUE_OOSEQ --- TCP队列到达顺序 应该是排序相关 TCP_MSS --- TCP最大段大小 TCP_CALCULATE_EFF_SEND_MSS --- 用于限制mms TCP_SND_BUF --- TCP发送缓冲空间(字节) TCP_SND_QUEUELEN ---TCP发送缓冲空间(pbufs) TCP_SNDLOWAT --- TCP写空间(字节) TCP_LISTEN_BACKLOG --- 启用TCP积压选择听协议控制块 TCP_DEFAULT_LISTEN_BACKLOG --- 容许最大协议控制块监听数 LWIP_TCP_TIMESTAMPS ---支持TCP时间戳选项 TCP_WND_UPDATE_THRESHOLD --- 窗口更新与触发 LWIP_EVENT_API LWIP_CALLBACK_API --- 只有一个为1 由系统控制或有回调函数控制 PBUF_LINK_HLEN --- 链路层头 PBUF_POOL_BUFSIZE --- pbuf池大小 LWIP_NETIF_HOSTNAME --- 使用dhcp_option_hostname用netif的主机名 lwip_netif_api --- 是否支持netif API,1为支持 LWIP_NETIF_STATUS_CALLBACK --- 回调函数支持接口 lwip_netif_link_callback --- 链路故障相关 lwip_netif_hwaddrhint --- 缓存链路层地址的提示 lwip_netif_loopback --- 支持发送数据包的目的地IP lwip_loopback_max_pbufs --- 在队列的最大数量的pbufs回送 LWIP_NETIF_LOOPBACK_MULTITHREADING --- 是否启用多线程 LWIP_NETIF_TX_SINGLE_PBUF --- 单一Pbuf发送 LWIP_HAVE_LOOPIF --- 支持回送地址(127.0.0.1) and loopif.c LWIP_HAVE_SLIPIF --- 支持滑动界面和slipif C TCPIP_THREAD_NAME --- 分配给主要的TCPIP线程的名称 tcpip_thread_stacksize --- 由主线程使用TCPIP栈大小 TCPIP_THREAD_PRIO --- 分配给主要的TCPIP线程优先级 tcpip_mbox_size --- 用于tcpip线程消息邮箱大小 SLIPIF_THREAD_NAME --- SLIPIF 线程名 SLIPIF_THREAD_STACKSIZE --- 分配给slipif_loop线程优先级 PPP_THREAD_NAME --- PPP协议线程名称 PPP_THREAD_STACKSIZE --- 由pppmain线程使用的堆栈大小 ppp_thread_prio --- 分配给pppmain线程优先级 DEFAULT_THREAD_NAME --- 默认LWIP线程名 DEFAULT_THREAD_STACKSIZE --- 缺省堆栈大小 default_thread_prio --- 分配给任何其余LwIP线程优先级 default_raw_recvmbox_size --- 其余raw邮箱大小 DEFAULT_UDP_RECVMBOX_SIZE --- 其余udp邮箱大小 DEFAULT_TCP_RECVMBOX_SIZE --- 其余tcp邮箱大小 DEFAULT_ACCEPTMBOX_SIZE --- ACCEPTMBOX大小 lwip_tcpip_core_locking --- (实验!)平时不用 lwip_netconn --- 使能netconn API(须要使用api_lib。C) lwip_socket --- 使Socket API (须要sockets.c) lwip_compat_sockets --- BSD套接字函数名称 lwip_posix_sockets_io_names ---使POSIX风格的套接字函数名称posix系统 LWIP_TCP_KEEPALIVE --- 死链检测 LWIP_SO_RCVBUF ---使能阻塞处理程序 RECV_BUFSIZE_DEFAULT --- 若使能阻塞处理,则该设置为阻塞缓冲大小 SO_REUSE --- 重发送 lwip_stats --- 使能lwip_stats统计 LWIP_STATS_DISPLAY --- 编译输出统计功能 LINK_STATS --- 使能链接统计 ETHARP_STATS --- 使能arp统计 IP_STATS --- 使能ip统计 IPFRAG_STATS --- ip碎片统计 ICMP_STATS --- icmp统计 IGMP_STATS ---igmp统计 UDP_STATS --- udp统计 TCP_STATS --- tcp统计 MEM_STATS ---内存管理统计 MEMP_STATS --- 内存链表统计 SYS_STATS --- 系通通计 PPP_SUPPORT --- 使能ppp协议 PPPOE_SUPPORT --- 使能pppoe协议 PPPOS_SUPPORT --- 使能pppos协议 NUM_PPP --- 最大ppp会话 PAP_SUPPORT --- 使能pap密码认证协议 CHAP_SUPPORT--- 使能chap协议 MSCHAP_SUPPORT --- 使能mschap目前不支持,不设置 CBCP_SUPPORT --- 使能CBCP 目前不支持,不设置 CCP_SUPPORT --- 使能ccp 目前不支持,不设置 VJ_SUPPORT --- 使能 支持该报头压缩 md5_support --- 支持MD5 FSM_DEFTIMEOUT --- 贞退出时间 FSM_DEFMAXTERMREQS --- 最大终止请求传输 FSM_DEFMAXCONFREQS --- 最大配置请求传输 FSM_DEFMAXNAKLOOPS --- NAK环的最大数量 UPAP_DEFTIMEOUT --- 重发请求超时(秒) UPAP_DEFREQTIME --- 时间等待认证请求同行 CHAP_DEFTIMEOUT --- chap默认退出时间 CHAP_DEFTRANSMITS --- 竞争最大发送时间 LCP_ECHOINTERVAL --- KeepAlive回送请求之间间隔,0秒为禁用 LCP_MAXECHOFAILS --- 故障以前悬而未决的回声请求数 PPP_MAXIDLEFLAG --- 最大发射空闲时间(在通过前发送标志字符) CHECKSUM_GEN_IP --- 生成ip包校验 CHECKSUM_GEN_UDP --- 生成udp包校验 CHECKSUM_GEN_TCP --- 生成tcp包校验 CHECKSUM_CHECK_IP ---传入ip包校验 CHECKSUM_CHECK_UDP ---传入udp包校验 CHECKSUM_CHECK_TCP --- 传入tcp包校验 如下是各类调试 LWIP_DBG_MIN_LEVEL LWIP_DBG_TYPES_ON ETHARP_DEBUG NETIF_DEBUG PBUF_DEBUG API_LIB_DEBUG API_MSG_DEBUG SOCKETS_DEBUG ICMP_DEBUG IGMP_DEBUG INET_DEBUG IP_DEBUG IP_REASS_DEBUG RAW_DEBUG MEM_DEBUG MEMP_DEBUG SYS_DEBUG TCP_DEBUG TCP_INPUT_DEBUG TCP_FR_DEBUG TCP_RTO_DEBUG TCP_CWND_DEBUG TCP_WND_DEBUG TCP_OUTPUT_DEBUG TCP_RST_DEBUG TCP_QLEN_DEBUG UDP_DEBUG TCPIP_DEBUG PPP_DEBUG SLIP_DEBUG DHCP_DEBUG AUTOIP_DEBUG SNMP_MSG_DEBUG SNMP_MIB_DEBUG DNS_DEBUG
在这里先说一下这两个配置lwip协议栈文件opt.h和lwipopts.h的关系:
opt.h是lwip“出厂”时原装的配置文件,它的做者是瑞士科学院的Adam等人,而lwipopts.h的做者是stellarisWare的工程师,它集合了opt.h中经常须要改动的部分和针对Stellaris所特有的配置选项添加进来了。这两个文件里边都配置的选项,之后者为准,不是共有的选项以它们各自的配置为准。web
在这里先说一下lwip的内存管理机制,咱们以enet_lwip这个例程为例。api
在使用lwip的时候,咱们可使用两种形式的内存,一种是heap,一种是pool。heap就像是一整块蛋糕,咱们须要多少就切多少,但 是切了以后不能吃,只能看,由于看完以后,你还要放回去让别人看,由于当整块蛋糕不多的时候,有不少人等着都要切了看,这样不少次的切了以后又放回去,必 然要产生一些很小的蛋糕块,这就是内存的碎片,到最后都是切得很细的蛋糕块,假如这个时候你想切块大点的蛋糕来看看,很差意思,你找遍了整个拼凑起来的蛋 糕块,没有发现你想要的那么大的,结果你只好放弃了,因此最后内存申请回频频失败。数组
由于咱们是嵌入式系统, 咱们的RAM再大也不能和PC机的天文数字相比,咱们不能使用PC机所使用的蛋糕刀具来切蛋糕,必须使用更小型的道具,占用CODE更小,这一点Adam 等相对于标准C而实现了几个小的内存分配、重分配和释放函数,它们都以mem_为前缀,已和原来的标准库函数相区别。固然若是你偏要使用大的刀,只须要
#define MEM_LIBC_MALLOC 1 。缓存
这几个工具无论你是heap型模式切蛋糕仍是pool模式切蛋糕,均可以用它们来完成,它们只是刀,至于怎么切蛋糕,这里不是它们该考虑的事情。安全
上面介绍了heap型的切蛋糕的方法,在简单说一下pool型切蛋糕的方法。网络
为了能让更多的人把蛋糕切回去看而且不至于还回来的蛋糕都是很是地小。Adam很是努力地在lwip切蛋糕上问题上采用一种Pool型的切法,找来一块蛋 糕,把它切成n等分,每一份都是相同的固定大小,一份不够的能够拿两份,一份用起来太多的人你也最少拿一份(虽然浪费了,可是你也必须这么作),这种切法 有两个好处,一是:如今你不能再随便的按本身的要求大小去切蛋糕了,大小是固定的,这样你申请了蛋糕以后不须要去切了,已经切好了,你能够很快地拿到一份 大小固定的蛋糕,这很是适合于在接受数据帧的底层使用,当大量的数据来的时候,咱们一会儿须要不少的内存,这种方式下,咱们很快就能够拿到足量的内存,不 至于目不暇接;二是:在切成多少份,每份多大上须要咱们根据最常接受到的数据帧的大小来费点脑筋,切得过小了,内存的利用率就降低了,切得太大了,咱们就 会严重地浪费内存,若是总共可切的内存还不大的话,那确定是要由于后面来的数据无蛋糕可切而要丢包的,这就像是如今的房地产,少数富人拥有好几套大房子空 着不住人,而另外一方面,多数穷人却由于租不起房子而只好离开大城市,可是当前穷人对于城市所做的贡献并不见得比富人小。多线程
这两种切法都不是完美的,也不可能有完美的,可是有它们最适合的地方。我上面的比喻是为了更形象地理解,固然在细节上可能会有不一样,不过,大致上就是这么个意思,细节咱们能够去深刻地分析。并发
Pool型通常用于从链路层就收一个帧,目的是快速、少碎片、浪费一点不要紧、只要我能知足大多数人迅速地有房可住便可。socket
heap型通常用于缓存应用层生成的数据,大小本身定,相切多少切多少,为所欲为,尽管之后可能没得切,但我只在意如今,也许之后就有新的方法解决呢,就像煤炭和石油,该用还得用,说不定之后会有新能源取代它们,杞人忧天干吗。
实际上,在enet_lwip这个例程里它就是这么实现的。
如何配置heap的大小呢,
#define MEM_SIZE (12 * 1024)
因此说当你有大量的数据要发送的时候,你最好把这个值设置得大一些。不然你会由于切不到heap中的内存而没法发送或只能延迟发送。
最好是把上面这个数设置成4字节对齐的。
如何配置pool的大小呢
#define PBUF_POOL_SIZE 16 #define PBUF_POOL_BUFSIZE 256
第一个是咱们要切的分数,第二个是每一份的大小。
那么实际上咱们切到的每一分内存的大小要比咱们定义的大16个字节。咱们能够根据应用去调整这几个值,这两部分的大小就占到了lwip协议栈所占内存的大部分,也就是说他们会影响到ZI段的大小。
若是要使发送的应用程序也 采用pool的方式而不是heap,则要:
#define MEM_USE_POOLS 1 #define MEM_USE_CUSTOM_POOLS 1
而且还要在工程所在目录下建立文件 lwippools.h,里包括:
LWIP_MALLOC_MEMPOOL_START LWIP_MALLOC_MEMPOOL(20, 256) LWIP_MALLOC_MEMPOOL(10, 512) LWIP_MALLOC_MEMPOOL(5, 1512) LWIP_MALLOC_MEMPOOL_END
这样协议栈所涉及到的内存都用POOL方式来管理了,这种方法在StellarisWare例程中通常没有采用。若是使用POOL,如下关于内存的两个函 数是不会被调用的: mem_init();这个函数主要是对堆内存的初始化,并返回指针。 mem_realloc(mem, size);这个函数对已分配的对内存块进行收缩。
//***************************************************************************** // // lwipopts.h - Configuration file for lwIP ************************************************************************* // // NOTE: This file has been derived from the lwIP/src/include/lwip/opt.h // header file. // 注:此文件起源于opt.h // For additional details, refer to the original "opt.h" file, and lwIP // documentation. // 详情参考opt.h。 //***************************************************************************** #ifndef __LWIPOPTS_H__ #define __LWIPOPTS_H__ //***************************************************************************** // // ---------- Stellaris / lwIP Port Options ---------- // //***************************************************************************** #define HOST_TMR_INTERVAL 100 // 主机定时器间隔,注意不是lwip协议栈自己的定时器间隔,可用来检查IP地址的获取状况或者周期性地调用一些函数。 //#define DHCP_EXPIRE_TIMER_MSECS (10 * 1000) //DHCP 获取超时的毫秒数。这个实际在例程中没看到有用到。DHCP获取IP超时,通常就会采用AUTOIP的方式自给IP。 //#define INCLUDE_HTTPD_SSI //在HTTPD中若是有含有SSI标签的网页存在,则开启它,不然若是是普通的html网页,不须要开启。 //#define INCLUDE_HTTPD_CGI //若是须要CGI的处理,则须要开启。 //#define DYNAMIC_HTTP_HEADERS //若是要动态的添加HTTP首部则开启,在使用makefsfile 带参数-h时,就去掉了http首部,若是不能正常浏览到网页可尝试开启。通常不须要开启,样能够节省Flash的空间,由于若是不是使用SD卡,而是使用内部文件系统的时候,全部的网页数据都放在了RO段。 //***************************************************************************** // // ---------- Platform specific locking ---------- // //***************************************************************************** #define SYS_LIGHTWEIGHT_PROT 1 // default is 0 针对Stellaris必须1,主要是由于在分配内存的时候,要确保总中断关闭。防止内存分配失败。 #define NO_SYS 1 // default is 0 若是为使用RTOS,就置1. //#define MEMCPY(dst,src,len) memcpy(dst,src,len) /* 该宏用来定义咱们是否须要C语言标准库函数memcpy(),若是有更有效的函数,该宏能够忽略.不适用C标准库 //#define SMEMCPY(dst,src,len) memcpy(dst,src,len) //同上 //***************************************************************************** // // ---------- Memory options ---------- // //***************************************************************************** //#define MEM_LIBC_MALLOC 0 //若是为1,就表示咱们使用c库的 malloc/free/realloc,不然使用lwip自带的函数,注意加了前缀的。 #define MEM_ALIGNMENT 4 //Stellaris该值必须为4,设置CPU的对齐方式 #define MEM_SIZE (12 * 1024) // default is 1600 该值在ZI中占了很大的份额。这就是堆内存的大小,若是应用程序有大量数据在发送是要被复制,那么该值就应该尽可能大一点。因而可知,发送缓冲区从这里边分配。 //#define MEMP_OVERFLOW_CHECK 0 //是否开启内存POOL溢出检查,便是否使能堆内存溢出检查. //#define MEMP_SANITY_CHECK 0 //设置为1表示在每次调用函数memp_free()后,进行一次正常的检查,以确保链表队列没有循环 //#define MEM_USE_POOLS 0 //是否使用POOL型内存来做为发送缓冲,而不是heap型,若是开启的话,可能还要建立头文件lwippool.h //#define MEMP_USE_CUSTOM_POOLS 0 //内存Pool是否使用固定大小的POOL,开启这个前提是要开启上面的。 //***************************************************************************** // // ---------- Internal Memory Pool Sizes ---------- // //***************************************************************************** #define MEMP_NUM_PBUF 20 //来自memp的PBUF_ROM和PBUF_REF类型的数目,若是应用程有大量的数据来自ROM或者静态mem的数据要发送,此值要设大一些。 //#define MEMP_NUM_RAW_PCB 4 //原始链接(就是应用程不通过传输层直接到IP层获取数据)PCB的数目,该项依赖lwip_raw项的开启。 //#define MEMP_NUM_UDP_PCB 4 //UDP的PCB数目,每一活动的UDP “链接” 须要一个PCB。 #define MEMP_NUM_TCP_PCB 3 // 同时创建激活的TCP链接的数目(要求参数LWIP_TCP使能).默认为5 我改为1以后和原来的8没有什么区别。可是这里创建tcp链接发送数据以后就马上关闭了tcp链接. //若是这里设置为1,就要注意了,咱们在点亮led的时候其实是几乎同时发送了两个GET请求,要求创建两个激活的tcp链接,若是设置为1,就会等到一个tcp激活的tcp链接关闭以后 //再创建一个新的tcp链接,因此才会出现延迟返回状态的现象。通过个人实验,发现等于3的时候比较特殊,会使code少4个字节。 //并且ZI的大小也只比2的时候多160,(奇数多160,偶数时多168)。 #define MEMP_NUM_TCP_PCB_LISTEN 1 /* 可以监听的TCP链接数目(要求参数LWIP_TCP使能).默认为8我改为了1以后对本例程也是无影响的。这个很是规律,多一个ZI就多32个字节。*/ #define MEMP_NUM_TCP_SEG 20 //最多同时在队列的TCP_SEG的数目.这个数为20,MEMP_NUM_TCP_PCB为3时,code会比其它状况要小4个字节,其它全部值时code大小不变,当从偶数增长到奇数时,ZI增长24,从奇数增长到偶数时ZI增长16。 //#define MEMP_NUM_REASSDATA 5 // 最多同时在队列等待重装的IP包数目,是整个IP包,不是IP分片。 //#define MEMP_NUM_ARP_QUEUE 30 // //#define MEMP_NUM_IGMP_GROUP 8 // //#define MEMP_NUM_SYS_TIMEOUT 3 // 可以同时激活的timeout的个数(要求NO_SYS==0)。默认为3 //#define MEMP_NUM_NETBUF 2 // netbufs结构的数目,仅当使用sequential API的时候须要。默认为2 //#define MEMP_NUM_NETCONN 4 // netconns结构的数目,仅当使用sequential API的时候须要。默认为4 //#define MEMP_NUM_TCPIP_MSG_API 8 // tcpip_msg结构的数目,它用于callback/timeout API的通讯(仅当使用tcpip.c的时候须要 )。默认为8 //#define MEMP_NUM_TCPIP_MSG_INPKT 8 // 接收包时tcpip_msg结构体的数目。 //***************************************************************************** // // ---------- ARP options ---------- // //***************************************************************************** //#define LWIP_ARP 1 //开启ARP //#define ARP_TABLE_SIZE 10 //ARP表项的大小。激活的MAC-IP地址对存储区的数目 //#define ARP_QUEUEING 1 //设置为1表示在硬件地址解析期间,将发送数据包放入到队列中 //#define ETHARP_TRUST_IP_MAC 1 //***************************************************************************** // // ---------- IP options ---------- // //***************************************************************************** //#define IP_FORWARD 0 //#define IP_OPTIONS_ALLOWED 1 #define IP_REASSEMBLY 0 // default is 1 注意进来的IP分段包就不会被重装,因此大于1500的IP包可能会有些意想不到的问题 #define IP_FRAG 0 // default is 1 这样从这里发送出去的包不会被分片。这个不会出现问题,由于咱们的TCP_MSS才512 //#define IP_REASS_MAXAGE 3 //#define IP_REASS_MAX_PBUFS 10 //#define IP_FRAG_USES_STATIC_BUF 1 //#define IP_FRAG_MAX_MTU 1500 //#define IP_DEFAULT_TTL 255 //***************************************************************************** // // ---------- ICMP options ---------- // //***************************************************************************** //#define LWIP_ICMP 1 //#define ICMP_TTL (IP_DEFAULT_TTL) //***************************************************************************** // // ---------- RAW options ---------- // //***************************************************************************** //#define LWIP_RAW 1 //#define RAW_TTL (IP_DEFAULT_TTL) //***************************************************************************** // // ---------- DHCP options ---------- // //***************************************************************************** #define LWIP_DHCP 1 // default is 0 //#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) //***************************************************************************** // // ---------- UPNP options ---------- // //***************************************************************************** //#define LWIP_UPNP 0 //***************************************************************************** // // ---------- PTPD options ---------- // //***************************************************************************** //#define LWIP_PTPD 0 //***************************************************************************** // // ---------- AUTOIP options ---------- // //***************************************************************************** #define LWIP_AUTOIP 1 // default is 0 #define LWIP_DHCP_AUTOIP_COOP ((LWIP_DHCP) && (LWIP_AUTOIP)) // default is 0 #define LWIP_DHCP_AUTOIP_COOP_TRIES 5 // default is 9 //***************************************************************************** // // ---------- SNMP options ---------- // //***************************************************************************** //#define LWIP_SNMP 0 //#define SNMP_CONCURRENT_REQUESTS 1 //#define SNMP_TRAP_DESTINATIONS 1 //#define SNMP_PRIVATE_MIB 0 //#define SNMP_SAFE_REQUESTS 1 //***************************************************************************** // // ---------- IGMP options ---------- // //***************************************************************************** //#define LWIP_IGMP 0 //***************************************************************************** // // ---------- DNS options ----------- // //***************************************************************************** //#define LWIP_DNS 0 //#define DNS_TABLE_SIZE 4 //#define DNS_MAX_NAME_LENGTH 256 //#define DNS_MAX_SERVERS 2 //#define DNS_DOES_NAME_CHECK 1 //#define DNS_USES_STATIC_BUF 1 //#define DNS_MSG_SIZE 512 //***************************************************************************** // // ---------- UDP options ---------- // //***************************************************************************** //#define LWIP_UDP 1 //#define LWIP_UDPLITE 0 //#define UDP_TTL (IP_DEFAULT_TTL) //***************************************************************************** // // ---------- TCP options ---------- // //***************************************************************************** //#define LWIP_TCP 1 //#define TCP_TTL (IP_DEFAULT_TTL) #define TCP_WND 2048 // default is 2048, was 4096 改变该值并不影响code和ZI的大小。 //#define TCP_MAXRTX 12 //#define TCP_SYNMAXRTX 6 //#define TCP_QUEUE_OOSEQ 1 #define TCP_MSS 512 // default is 128, was 1500 改变该值并不影响code和ZI的大小。。该值规定了TCP数据包数据部分的最大值,不包括tcp首部 //#define TCP_CALCULATE_EFF_SEND_MSS 1 #define TCP_SND_BUF (6 * TCP_MSS) //改变该值并不影响ZI的大小,但稍稍影响code大小,几个字节。 // default is 256 //#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF/TCP_MSS)) //#define TCP_SNDLOWAT (TCP_SND_BUF/2) //#define TCP_LISTEN_BACKLOG 0 //#define TCP_DEFAULT_LISTEN_BACKLOG 0xff //***************************************************************************** // // ---------- API options ---------- // //***************************************************************************** //#define LWIP_EVENT_API 0 //#define LWIP_CALLBACK_API 1 //***************************************************************************** // // ---------- Pbuf options ---------- // //***************************************************************************** #define PBUF_LINK_HLEN 16 // default is 14 改为16是由于在Stellaris系列中,FIFO中的帧是开始有两个字节的帧长度,针对Stellaris必须16 #define PBUF_POOL_SIZE 16 // 奇数时code比偶数时多4个字节,每+1,RAM多消耗272个字节。这也就是说每一个pbuf须要272个字节,而每个pbuf //由两部分组成,一部分是缓冲区256个字节,一部分是pbuf首部(16个字节。)(不是以太网链路层的帧首部,尽管它从FIFO中是16个字节)。这个pbuf就是直接装入从RX FIFO中传 //过来的数据。每个pbuf能够存一个帧,能够存256个字节的一个帧。这部份内存主要用来接收的。 #define PBUF_POOL_BUFSIZE 256 //这个pbuf包括前边的16个字节的pbuf头,叫首部有点不合适,这个pbuf头里保存这个pbuf的全部信息。 // default is LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) #define ETH_PAD_SIZE 2 // default is 0 针对Stellaris必须为2 //***************************************************************************** // // ---------- Network Interfaces options ---------- // //***************************************************************************** //#define LWIP_NETIF_HOSTNAME 0 //#define LWIP_NETIF_API 0 //#define LWIP_NETIF_STATUS_CALLBACK 0 //#define LWIP_NETIF_LINK_CALLBACK 0 //#define LWIP_NETIF_HWADDRHINT 0 //***************************************************************************** // // ---------- LOOPIF options ---------- // //***************************************************************************** //#define LWIP_HAVE_LOOPIF 0 //#define LWIP_LOOPIF_MULTITHREADING 1 //***************************************************************************** // // ---------- Thread options ---------- // //***************************************************************************** //#define TCPIP_THREAD_NAME "tcpip_thread" //#define TCPIP_THREAD_STACKSIZE 0 //#define TCPIP_THREAD_PRIO 1 //#define TCPIP_MBOX_SIZE 0 //#define SLIPIF_THREAD_NAME "slipif_loop" //#define SLIPIF_THREAD_STACKSIZE 0 //#define SLIPIF_THREAD_PRIO 1 //#define PPP_THREAD_NAME "pppMain" //#define PPP_THREAD_STACKSIZE 0 //#define PPP_THREAD_PRIO 1 //#define DEFAULT_THREAD_NAME "lwIP" //#define DEFAULT_THREAD_STACKSIZE 0 //#define DEFAULT_THREAD_PRIO 1 //#define DEFAULT_RAW_RECVMBOX_SIZE 0 //#define DEFAULT_UDP_RECVMBOX_SIZE 0 //#define DEFAULT_TCP_RECVMBOX_SIZE 0 //#define DEFAULT_ACCEPTMBOX_SIZE 0 //***************************************************************************** // // ---------- Sequential layer options ---------- // //***************************************************************************** //#define LWIP_TCPIP_CORE_LOCKING 0 #define LWIP_NETCONN 0 // default is 1 //***************************************************************************** // // ---------- Socket Options ---------- // //***************************************************************************** #define LWIP_SOCKET 0 // default is 1 //#define LWIP_COMPAT_SOCKETS 1 //#define LWIP_POSIX_SOCKETS_IO_NAMES 1 //#define LWIP_TCP_KEEPALIVE 0 //#define LWIP_SO_RCVTIMEO 0 //#define LWIP_SO_RCVBUF 0 //#define SO_REUSE 0 //***************************************************************************** // // ---------- Statistics options ---------- // //***************************************************************************** //#define LWIP_STATS 1 //#define LWIP_STATS_DISPLAY 0 //#define LINK_STATS 1 //#define ETHARP_STATS (LWIP_ARP) //#define IP_STATS 1 //#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) //#define ICMP_STATS 1 //#define IGMP_STATS (LWIP_IGMP) //#define UDP_STATS (LWIP_UDP) //#define TCP_STATS (LWIP_TCP) //#define MEM_STATS 1 //#define MEMP_STATS 1 //#define SYS_STATS 1 //***************************************************************************** // // ---------- PPP options ---------- // //***************************************************************************** //#define PPP_SUPPORT 0 //#define PPPOE_SUPPORT 0 //#define PPPOS_SUPPORT PPP_SUPPORT #if PPP_SUPPORT //#define NUM_PPP 1 //#define PAP_SUPPORT 0 //#define CHAP_SUPPORT 0 //#define MSCHAP_SUPPORT 0 //#define CBCP_SUPPORT 0 //#define CCP_SUPPORT 0 //#define VJ_SUPPORT 0 //#define MD5_SUPPORT 0 //#define FSM_DEFTIMEOUT 6 //#define FSM_DEFMAXTERMREQS 2 //#define FSM_DEFMAXCONFREQS 10 //#define FSM_DEFMAXNAKLOOPS 5 //#define UPAP_DEFTIMEOUT 6 //#define UPAP_DEFREQTIME 30 //#define CHAP_DEFTIMEOUT 6 //#define CHAP_DEFTRANSMITS 10 //#define LCP_ECHOINTERVAL 0 //#define LCP_MAXECHOFAILS 3 //#define PPP_MAXIDLEFLAG 100 //#define PPP_MAXMTU 1500 //#define PPP_DEFMRU 296 #endif //***************************************************************************** // // ---------- checksum options ---------- // //***************************************************************************** //#define CHECKSUM_GEN_IP 1 //#define CHECKSUM_GEN_UDP 1 //#define CHECKSUM_GEN_TCP 1 //#define CHECKSUM_CHECK_IP 1 //#define CHECKSUM_CHECK_UDP 1 //#define CHECKSUM_CHECK_TCP 1 //***************************************************************************** // // ---------- Debugging options ---------- // //***************************************************************************** #if 0 #define U8_F "c" #define S8_F "c" #define X8_F "x" #define U16_F "u" #define S16_F "d" #define X16_F "x" #define U32_F "u" #define S32_F "d" #define X32_F "x" extern void UARTprintf(const char *pcString, ...); #define LWIP_PLATFORM_DIAG(x) {UARTprintf x;} #define LWIP_DEBUG #endif //#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_OFF #define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_WARNING //#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_SERIOUS //#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_SEVERE //#define LWIP_DBG_TYPES_ON LWIP_DBG_ON #define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH) //#define ETHARP_DEBUG LWIP_DBG_ON // default is OFF //#define NETIF_DEBUG LWIP_DBG_ON // default is OFF //#define PBUF_DEBUG LWIP_DBG_ON //#define API_LIB_DEBUG LWIP_DBG_OFF //#define API_MSG_DEBUG LWIP_DBG_OFF //#define SOCKETS_DEBUG LWIP_DBG_OFF //#define ICMP_DEBUG LWIP_DBG_OFF //#define IGMP_DEBUG LWIP_DBG_OFF //#define INET_DEBUG LWIP_DBG_OFF //#define IP_DEBUG LWIP_DBG_ON // default is OFF //#define IP_REASS_DEBUG LWIP_DBG_OFF //#define RAW_DEBUG LWIP_DBG_OFF //#define MEM_DEBUG LWIP_DBG_OFF //#define MEMP_DEBUG LWIP_DBG_OFF //#define SYS_DEBUG LWIP_DBG_OFF //#define TCP_DEBUG LWIP_DBG_OFF //#define TCP_INPUT_DEBUG LWIP_DBG_OFF //#define TCP_FR_DEBUG LWIP_DBG_OFF //#define TCP_RTO_DEBUG LWIP_DBG_OFF //#define TCP_CWND_DEBUG LWIP_DBG_OFF //#define TCP_WND_DEBUG LWIP_DBG_OFF //#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF //#define TCP_RST_DEBUG LWIP_DBG_OFF //#define TCP_QLEN_DEBUG LWIP_DBG_OFF //#define UDP_DEBUG LWIP_DBG_ON // default is OFF //#define TCPIP_DEBUG LWIP_DBG_OFF //#define PPP_DEBUG LWIP_DBG_OFF //#define SLIP_DEBUG LWIP_DBG_OFF //#define DHCP_DEBUG LWIP_DBG_ON // default is OFF //#define AUTOIP_DEBUG LWIP_DBG_OFF //#define SNMP_MSG_DEBUG LWIP_DBG_OFF //#define SNMP_MIB_DEBUG LWIP_DBG_OFF //#define DNS_DEBUG LWIP_DBG_OFF #define HTTPD_DEBUG LWIP_DBG_ON #endif /* __LWIPOPTS_H__ */
如何去配置lwip,使它去适合不一样大小的脚,这就是本贴的主题lwIP的配置问题。尤为是内存的配置,配置多了浪费,配置少了跑不了或者不稳定(会出现的一大堆莫名奇妙的问题,什么打开网页的速度很慢啊?什么丢包啊,什么死机啦,什么跑到无限循环里边去了,总之不少)。
在这里先说一下这两个配置lwip协议栈文件opt.h和lwipopts.h的关系:
opt.h是lwip“出厂”时原装的配置文件,它的做者是瑞士科学院的Adam等人,而lwipopts.h的做者是stellarisWare的工程师,它集合了opt.h中经常须要改动的部分和针对Stellaris所特有的配置选项添加进来了。这两个文件里边都配置的选项,之后者为准,不是共有的选项以它们各自的配置为准。
在这里先说一下lwip的内存管理机制,咱们以enet_lwip这个例程为例。
在使用lwip的时候,咱们可使用两种形式的内存,一种是heap(mem.c文件-mem_malloc()),一种是pool(memp.c文件-memp_malloc())。heap就像是一整块蛋糕,咱们须要多少就切多少,可是切了以后不能吃,只能看,由于看完以后,你还要放回去让别人看,由于当整块蛋糕不多的时候,有不少人等着都要切了看,这样不少次的切了以后又放回去,必然要产生一些很小的蛋糕块,这就是内存的碎片,到最后都是切得很细的蛋糕块,假如这个时候你想切块大点的蛋糕来看看,很差意思,你找遍了整个拼凑起来的蛋糕块,没有发现你想要的那么大的,结果你只好放弃了,因此最后内存申请回频频失败。
由于咱们是嵌入式系统,咱们的RAM再大也不能和PC机的天文数字相比,咱们不能使用PC机所使用的蛋糕刀具来切蛋糕,必须使用更小型的道具,占用CODE更小,这一点Adam等相对于标准C而实现了几个小的内存分配、重分配和释放函数,它们都以mem_为前缀,已和原来的标准库函数相区别。固然若是你偏要使用大的刀,只须要
#define MEM_LIBC_MALLOC 1 。
这几个工具无论你是heap型模式切蛋糕仍是pool模式切蛋糕,均可以用它们来完成,它们只是刀,至于怎么切蛋糕,这里不是它们该考虑的事情。
上面介绍了heap型的切蛋糕的方法,在简单说一下pool型切蛋糕的方法。
为了能让更多的人把蛋糕切回去看而且不至于还回来的蛋糕都是很是地小。Adam很是努力地在lwip切蛋糕上问题上采用一种Pool型的切法,找来一块蛋糕,把它切成n等分,每一份都是相同的固定大小,一份不够的能够拿两份,一份用起来太多的人你也最少拿一份(虽然浪费了,可是你也必须这么作),这种切法有两个好处,一是:如今你不能再随便的按本身的要求大小去切蛋糕了,大小是固定的,这样你申请了蛋糕以后不须要去切了,已经切好了,你能够很快地拿到一份大小固定的蛋糕,这很是适合于在接受数据帧的底层使用,当大量的数据来的时候,咱们一会儿须要不少的内存,这种方式下,咱们很快就能够拿到足量的内存,不至于目不暇接;二是:在切成多少份,每份多大上须要咱们根据最常接受到的数据帧的大小来费点脑筋,切得过小了,内存的利用率就降低了,切得太大了,咱们就会严重地浪费内存,若是总共可切的内存还不大的话,那确定是要由于后面来的数据无蛋糕可切而要丢包的,这就像是如今的房地产,少数富人拥有好几套大房子空着不住人,而另外一方面,多数穷人却由于租不起房子而只好离开大城市,可是当前穷人对于城市所做的贡献并不见得比富人小。
这两种切法都不是完美的,也不可能有完美的,可是有它们最适合的地方。我上面的比喻是为了更形象地理解,固然在细节上可能会有不一样,不过,大致上就是这么个意思,细节咱们能够去深刻地分析。
Pool型通常用于从链路层就收一个帧,目的是快速、少碎片、浪费一点不要紧、只要我能知足大多数人迅速地有房可住便可。
heap型通常用于缓存应用层生成的数据,大小本身定,相切多少切多少,为所欲为,尽管之后可能没得切,但我只在意如今,也许之后就有新的方法解决呢,就像煤炭和石油,该用还得用,说不定之后会有新能源取代它们,杞人忧天干吗。
实际上,在enet_lwip这个例程里它就是这么实现的。
如何配置heap的大小呢,
#define MEM_SIZE (12 * 1024) // ----实际空间即固定数组ram_heap[]中 (用于PBUF_RAM类型 p->len = p->tot_len) //主要mem.c文件---mem_malloc() #define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) static u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
因此说当你有大量的数据要发送的时候,你最好把这个值设置得大一些。不然你会由于切不到heap中的内存而没法发送或只能延迟发送。
最好是把上面这个数设置成4字节对齐的。
如何配置pool的大小呢,
#define PBUF_POOL_SIZE 16 #define PBUF_POOL_BUFSIZE 256 ---实际空间即固定数组memp_memory[]中(PBUF_POOL类型 p->tot_len= p->len + p->len.....) 主要memp.c文件---memp_malloc() LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL") 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" ]; case PBUF_POOL: p = memp_malloc(MEMP_PBUF_POOL); case PBUF_RAM: p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length)); case PBUF_ROM: case PBUF_REF: /* only allocate memory for the pbuf structure */ p = memp_malloc(MEMP_PBUF);
第一个是咱们要切的分数,第二个是每一份的大小。
那么实际上咱们切到的每一分内存的大小要比咱们定义的大16个字节。咱们能够根据应用去调整这几个值,这两部分的大小就占到了lwip协议栈所占内存的大部分,也就是说他们会影响到ZI段的大小。
若是要使发送的应用程序也采用pool的方式而不是heap,则要:
#define MEM_USE_POOLS 1 define MEM_USE_CUSTOM_POOLS 1
而且还要在工程所在目录下建立文件
lwippools.h,里包括:
LWIP_MALLOC_MEMPOOL_START LWIP_MALLOC_MEMPOOL(20, 256) LWIP_MALLOC_MEMPOOL(10, 512) LWIP_MALLOC_MEMPOOL(5, 1512) LWIP_MALLOC_MEMPOOL_END
这样协议栈所涉及到的内存都用POOL方式来管理了,这种方法在StellarisWare例程中通常没有采用。 若是使用POOL,如下关于内存的两个函数是不会被调用的: mem_init();这个函数主要是对堆内存的初始化,并返回指针。 mem_realloc(mem, size);这个函数对已分配的对内存块进行收缩。