struct pbuf *pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
{
struct pbuf *p, *q, *r;
u16_t offset;
s32_t rem_len; /* remaining length *//* determine header offset */
switch (layer) {
case PBUF_TRANSPORT:
/* add room for transport (often TCP) layer header */
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;
break;
case PBUF_IP:
/* add room for IP layer header */
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN;
break;
case PBUF_LINK:
/* add room for link layer header */
offset = PBUF_LINK_HLEN;
break;
case PBUF_RAW:
offset =0;
break;
default:
LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
returnNULL;
}
switch (type) {
//申请PBUF_POOL类型的内存池case PBUF_POOL:
/* allocate head of pbuf chain into p */
p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
if (p ==NULL) {
PBUF_POOL_IS_EMPTY();
returnNULL;
}
p->type=type;
p->next =NULL;
/* make the payload pointer point 'offset' bytes into pbuf data memory *///pbuf链表的第一个pbuf需填写协议头部字节
p->payload = LWIP_MEM_ALIGN((void*)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset)));
p->tot_len = length;
// 判断一个pbuf_pool能否装下申请字节数
p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset));
/* set reference count (needed here in case we fail) */
p->ref =1;
/* remember first pbuf for linkage in next iteration */
r = p;
/* remaining length to be allocated */
rem_len = length - p->len;
/* any remaining pbufs to be allocated? *///若一个pbuf_pool装不下申请字节数,则生成pbuf链表while (rem_len >0) {
q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
if (q ==NULL) {
PBUF_POOL_IS_EMPTY();
/* free chain so far allocated */
pbuf_free(p);
/* bail out unsuccesfully */returnNULL;
}
q->type=type;
q->flags =0;
q->next =NULL;
/* make previous pbuf point to this pbuf *///连接pbuf
r->next = q;
/* set total length of this pbuf and next in chain */
q->tot_len = (u16_t)rem_len;
/* this pbuf length is pool size, unless smaller sized tail */
q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED);
//第二个pbuf不需要装在协议头部字节
q->payload = (void*)((u8_t *)q + SIZEOF_STRUCT_PBUF);
q->ref =1;
/* calculate remaining length to be allocated */
rem_len -= q->len;
/* remember this pbuf for linkage in next iteration */
r = q;
}
/* end of chain *//*r->next = NULL;*/
break;
//采用内存堆函数对pbuf申请case PBUF_RAM:
/* If pbuf is to be allocated in RAM, allocate memory for it. */
p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length));
if (p ==NULL) {
returnNULL;
}
/* Set up internal structure of the pbuf. */
p->payload = LWIP_MEM_ALIGN((void*)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset));
p->len = p->tot_len = length;
p->next =NULL;
p->type=type;
break;
/* pbuf references existing (non-volatile static constant) ROM payload? */case PBUF_ROM:
/* pbuf references existing (externally allocated) RAM payload? *///申请PBUF类型的内存池case PBUF_REF:
/* only allocate memory for the pbuf structure */
p = (struct pbuf *)memp_malloc(MEMP_PBUF);
if (p ==NULL) {
returnNULL;
}
/* caller must set this field properly, afterwards */
p->payload =NULL;
p->len = p->tot_len = length;
p->next =NULL;
p->type=type;
break;
default:
LWIP_ASSERT("pbuf_alloc: erroneous type", 0);
returnNULL;
}
/* set reference count */
p->ref =1;
/* set flags */
p->flags =0;
return p;
}
4、pbuf_free
u8_t pbuf_free(struct pbuf *p)
{
u16_t type;struct pbuf *q;
u8_t count;
if (p == NULL) {
return0;
}
count = 0;
/* de-allocate all consecutive pbufs from the head of the chain that
* obtain a zero reference count after decrementing*/
while (p != NULL) {
u16_t ref;
SYS_ARCH_DECL_PROTECT(old_level);
/* Since decrementing ref cannot be guaranteed to be a single machine operation
* we must protect it. We put the new ref into a local variable to prevent
* further protection. */
SYS_ARCH_PROTECT(old_level);
/* all pbufs in a chain are referenced at least once */
LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
/* decrease reference count (number of pointers to pbuf) */
ref = --(p->ref);
SYS_ARCH_UNPROTECT(old_level);
/* this pbuf is no longer referenced to? */
//如果该pbuf内的ref为0,则释放该pbufif (ref == 0) {
/* remember next pbuf in chain for next iteration */
q = p->next;
type = p->type;
{
/* is this a pbuf from the pool? */
if (type == PBUF_POOL) {
memp_free(MEMP_PBUF_POOL, p);
/* is this a ROM or RAM referencing pbuf? */
} elseif (type == PBUF_ROM || type == PBUF_REF) {
memp_free(MEMP_PBUF, p);
/* type == PBUF_RAM */
} else {
mem_free(p);
}
}
count++;
/* proceed to next pbuf */
p = q;
/* p->ref > 0, this pbuf is still referenced to */
/* (and so the remaining pbufs in chain as well) */
} else {
/* stop walking through the chain */
p = NULL;
}
}
PERF_STOP("pbuf_free");
/* return number of de-allocated pbufs */
return count;
}