物联网LWIP网络开发 LWIP网卡设计原理11.1 协议栈内存管理

lwIP协议栈内存管理上

lwIP 内存管理需求

常用内存管理需求

  • 静态分配的变量 -> RAM
  • 任务堆栈
  • 动态存储器管理 malloc & free

lwip内存管理需求

物联网LWIP网络开发 LWIP网卡设计原理11.1 协议栈内存管理_第1张图片

lwip 内存管理方案

堆 heap

物联网LWIP网络开发 LWIP网卡设计原理11.1 协议栈内存管理_第2张图片

  1. C standard library
  2. lwIP 堆分配(需要保留一块内存)

池 pool

物联网LWIP网络开发 LWIP网卡设计原理11.1 协议栈内存管理_第3张图片

  1. 分配内存更快 效率更高
  2. 协议控制块(TCP UDP IP)
  3. 需要保留一块内存

lwIP 内存池管理

API

//内存池初始化
void  memp_init(void);
//内存池分配
void *memp_malloc(memp_t type);
//内存池释放
void  memp_free(memp_t type, void *mem);

lwIP内存堆管理

API

//内存堆初始化
void  mem_init(void);
//内存堆分配内存
void *mem_malloc(mem_size_t size);
//内存堆释放内存
void  mem_free(void *mem);

LwIP协议栈内存管理下

网络数据包管理

pbuf就是一个描述协议栈中数据包的数据结构,LwIP 中在 pbuf.c和 pubf.h实现了协议栈数据包管理的所有函数与数据结构

物联网LWIP网络开发 LWIP网卡设计原理11.1 协议栈内存管理_第4张图片

pbuf 数据结构

pbuf结构体

//pbuf.h
/** Main packet buffer struct */
struct pbuf {
  /** next pbuf in singly linked pbuf chain */
  struct pbuf *next;

  /** pointer to the actual data in the buffer */
  void *payload;

  /**
   * total length of this buffer and all next buffers in chain
   * belonging to the same packet.
   *
   * For non-queue packet chains this is the invariant:
   * p->tot_len == p->len + (p->next? p->next->tot_len: 0)
   */
  u16_t tot_len;

  /** length of this buffer */
  u16_t len;

  /** pbuf_type as u8_t instead of enum to save space */
  u8_t /*pbuf_type*/ type;

  /** misc flags */
  u8_t flags;

  /**
   * the reference count always equals the number of pointers
   * that refer to this pbuf. This can be pointers from an application,
   * the stack itself, or pbuf->next pointers from a chain.
   */
  u16_t ref;
};

pbuf类型

//pbuf.h
typedef enum {
  /** pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payloadare allocated in one piece of contiguous memory (so the first payload bytecan be calculated from struct pbuf).pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that mightchange in future versions).This should be used for all OUTGOING packets (TX).*/
  PBUF_RAM,
  /** pbuf data is stored in ROM, i.e. struct pbuf and its payload are located intotally different memory areas. Since it points to ROM, payload does nothave to be copied when queued for transmission. */
  PBUF_ROM,
  /** pbuf comes from the pbuf pool. Much like PBUF_ROM but payload might changeso it has to be duplicated when queued before transmitting, depending onwho has a 'ref' to it. */
  PBUF_REF,
  /** pbuf payload refers to RAM. This one comes from a pool and should be usedfor RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, structpbuf and its payload are allocated in one piece of contiguous memory (sothe first payload byte can be calculated from struct pbuf).Don't use this for TX, if the pool becomes empty e.g. because of TCP queuing,you are unable to receive TCP acks! */
  PBUF_POOL
} pbuf_type;

pbuf层

//pbuf.h
typedef enum {
  /** Includes spare room for transport layer header, e.g. UDP header.
   * Use this if you intend to pass the pbuf to functions like udp_send().
   */
  PBUF_TRANSPORT,
  /** Includes spare room for IP header.
   * Use this if you intend to pass the pbuf to functions like raw_send().
   */
  PBUF_IP,
  /** Includes spare room for link layer header (ethernet header).
   * Use this if you intend to pass the pbuf to functions like ethernet_output().
   * @see PBUF_LINK_HLEN
   */
  PBUF_LINK,
  /** Includes spare room for additional encapsulation header before ethernet
   * headers (e.g. 802.11).
   * Use this if you intend to pass the pbuf to functions like netif->linkoutput().
   * @see PBUF_LINK_ENCAPSULATION_HLEN
   */
  PBUF_RAW_TX,
  /** Use this for input packets in a netif driver when calling netif->input()
   * in the most common case - ethernet-layer netif driver. */
  PBUF_RAW
} pbuf_layer;

pbuf API

pbuf_alloc

//pbuf.c
/**
 * @ingroup pbuf
 * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
 *
 * The actual memory allocated for the pbuf is determined by the
 * layer at which the pbuf is allocated and the requested size
 * (from the size parameter).
 *
 * @param layer flag to define header size
 * @param length size of the pbuf's payload
 * @param type this parameter decides how and where the pbuf
 * should be allocated as follows:
 *
 * - PBUF_RAM: buffer memory for pbuf is allocated as one large
 *             chunk. This includes protocol headers as well.
 * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for
 *             protocol headers. Additional headers must be prepended
 *             by allocating another pbuf and chain in to the front of
 *             the ROM pbuf. It is assumed that the memory used is really
 *             similar to ROM in that it is immutable and will not be
 *             changed. Memory which is dynamic should generally not
 *             be attached to PBUF_ROM pbufs. Use PBUF_REF instead.
 * - PBUF_REF: no buffer memory is allocated for the pbuf, even for
 *             protocol headers. It is assumed that the pbuf is only
 *             being used in a single thread. If the pbuf gets queued,
 *             then pbuf_take should be called to copy the buffer.
 * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from
 *              the pbuf pool that is allocated during pbuf_init().
 *
 * @return the allocated pbuf. If multiple pbufs where allocated, this
 * is the first pbuf of a pbuf chain.
 */
struct pbuf *pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type);

pbuf_free

//pbuf.c
/**
 * @ingroup pbuf
 * Dereference a pbuf chain or queue and deallocate any no-longer-used
 * pbufs at the head of this chain or queue.
 *
 * Decrements the pbuf reference count. If it reaches zero, the pbuf is
 * deallocated.
 *
 * For a pbuf chain, this is repeated for each pbuf in the chain,
 * up to the first pbuf which has a non-zero reference count after
 * decrementing. So, when all reference counts are one, the whole
 * chain is free'd.
 *
 * @param p The pbuf (chain) to be dereferenced.
 *
 * @return the number of pbufs that were de-allocated
 * from the head of the chain.
 *
 * @note MUST NOT be called on a packet queue (Not verified to work yet).
 * @note the reference counter of a pbuf equals the number of pointers
 * that refer to the pbuf (or into the pbuf).
 *
 * @internal examples:
 *
 * Assuming existing chains a->b->c with the following reference
 * counts, calling pbuf_free(a) results in:
 *
 * 1->2->3 becomes ...1->3
 * 3->3->3 becomes 2->3->3
 * 1->1->2 becomes ......1
 * 2->1->1 becomes 1->1->1
 * 1->1->1 becomes .......
 *
 */
u8_t pbuf_free(struct pbuf *p);

pbuf_realloc

//pbuf.c
/**
 * @ingroup pbuf
 * Shrink a pbuf chain to a desired length.
 *
 * @param p pbuf to shrink.
 * @param new_len desired new length of pbuf chain
 *
 * Depending on the desired length, the first few pbufs in a chain might
 * be skipped and left unchanged. The new last pbuf in the chain will be
 * resized, and any remaining pbufs will be freed.
 *
 * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.
 * @note May not be called on a packet queue.
 *
 * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain).
 */
void pbuf_realloc(struct pbuf *p, u16_t new_len);

pbuf_header

//pbuf.c
/**
 * Adjusts the payload pointer to hide or reveal headers in the payload.
 *
 * Adjusts the ->payload pointer so that space for a header
 * (dis)appears in the pbuf payload.
 *
 * The ->payload, ->tot_len and ->len fields are adjusted.
 *
 * @param p pbuf to change the header size.
 * @param header_size_increment Number of bytes to increment header size which
 * increases the size of the pbuf. New space is on the front.
 * (Using a negative value decreases the header size.)
 * If hdr_size_inc is 0, this function does nothing and returns successful.
 *
 * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
 * the call will fail. A check is made that the increase in header size does
 * not move the payload pointer in front of the start of the buffer.
 * @return non-zero on failure, zero on success.
 *
 */
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment);

//pbuf.c
/**
 * @ingroup pbuf
 * Copy application supplied data into a pbuf.
 * This function can only be used to copy the equivalent of buf->tot_len data.
 *
 * @param buf pbuf to fill with data
 * @param dataptr application supplied data buffer
 * @param len length of the application supplied data buffer
 *
 * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough
 */
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);

你可能感兴趣的:(lwIP网络,lwip)