感觉这几个货得先交代一下,我也不知道为什么。
目录
在系统最开始初始化 Lwip 时,会初始化全局的 mbox 并创建 tcpip_thread。
mbox && tcpip_thread
mbox 是其他线程与 tcpip_thread 交互的桥梁。TCP 建立、拆除、数据收发等使用到 Lwip 内核函数的地方,都需要先将对应类型的 tcpip_msg 塞到 mbox 中,tcpip_thread 从 mbox 中顺序取出 tcpip_msg 并执行相应操作。
其实 mbox 就是一个队列,队列长度即队列可以放几个 Item 是可配的(TCPIP_MBOX_SIZE),每个 Item 即一个指针,指向 tcpip_msg。
tcpip_thread 的优先级一般较高,保证内核操作快速响应。有多高呢,比一般高还高一点~
mempool
前几天看到这块,觉得源码很丑,觉得源码装X。后来深入了一点,觉得这种设计很巧妙。于是我就默默把之前吐槽的一大段废话都删了。
mempool 即 Lwip 内部使用的内存池,就是预分配了内部需要使用的各种类型的结构,当需要用到某种类型的结构时,直接从对应池子中取就可以啦。
内存池即如下的一个大数组,所定义的各种类型的结构在 memp_std.h 中。
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"
];
举几个栗子看看(memp_std.h):
LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN")
#if LWIP_TCP
LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB")
LWIP_MEMPOOL(TCP_PCB_LISTEN,MEMP_NUM_TCP_PCB_LISTEN,sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN")LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg),"TCP_SEG")
#endif /* LWIP_TCP */LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM")
LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL")
如上,
前一章当我们创建一个 TCP 连接时,就会从 NETCONN 池子中拿一个 struct netconn,再从 TCP_PCB 池子中拿一个 struct tcp_pcb,然后把两者绑一块!
TCP_PCB 的内存池,大小为 MEMP_NUM_TCP_PCB * sizeof(struct tcp_pcb),有 MEMP_NUM_TCP_PCB 个 struct tcp_pcb,用一个取一个,用完了再还回来。最多可以创建 MEMP_NUM_TCP_PCB 个 TCP 连接。
PBUF_POOL 的内存池,有 PBUF_POOL_SIZE 个 pBUF,每个大小为 PBUF_POOL_BUFSIZE。Lwip 内部的 seg 都用 pBUF 存储,当某个连接占用很多 pBUF时(由于某种原因导致收不到ACK,数据包释放不了),其他连接可能出现 pBUF 不够用的情况,数据收发也会受到影响。多说一句,pBUF 也分不同的类型,这里的 pBUF 只是其中一种类型(PBUF_POOL),还有其他类型:PBUF_RAM、PBUF_ROM、PBUF_REF。其中 PBUF_RAM 在 Lwip heap 中动态分配内存,PBUF_ROM 和 PBUF_REF 在上面的 PBUF 池子中分配一个 struct pbuf 的结构,其 payload 指向其他数据。
每种类型的内存池,初始化时都会将每个结构用单链表链起来,用到时从表头取走,用完后再回收插入表头。
这一章就这些吧,水平有限,多了也没啥说的。