1. PBUF_RAM一次性分配size大小的连续内存
2. RBUF_ROM只需要分配小小的管理pbuf的控制管理内存
3. PBUF_ROOL分配一个链表,链表上每个元素所管理的内存最大不超过PBUF_POOL_BUFSIZE,它更像linux
   中的kmem_alloc内存高速缓存机制,所以它也更适合在网卡驱动irq中断中为刚刚到来的网络数据包申请存储空间
/*-----------------------------------------------------------------------------------*/
/* pbuf_alloc():
 *
 * Allocates a pbuf at protocol layer l. 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). The
 * flag 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. 
 * * RBUF_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.           
 * * PBUF_ROOL: the pbuf is allocated as a pbuf chain, with pbufs from
 *              the pbuf pool that is allocated during pbuf_init().
 */
/*-----------------------------------------------------------------------------------*/
struct pbuf *
pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag)
{
  struct pbuf *p, *q, *r;
  u16_t offset;
  s32_t rsize;

offset = 0;
  switch(l) {
  case PBUF_TRANSPORT:  // 如果为传输层申请pbuf,那么有效数据的偏移位置为PBUF_TRANSPORT_HLEN[luther.gliethttp]
    offset += PBUF_TRANSPORT_HLEN;
    /* FALLTHROUGH */
  case PBUF_IP:         // 如果为ip层申请pbuf,那么有效数据的偏移位置为PBUF_IP_HLEN+PBUF_LINK_HLEN
    offset += PBUF_IP_HLEN;
    offset += PBUF_LINK_HLEN;
    /* FALLTHROUGH */
  case PBUF_LINK:       // 如果是链路层申请pbuf内存,那么数据偏移位置就是0
    break;
  case PBUF_RAW:
    break;
  default:
    ASSERT("pbuf_alloc: bad pbuf layer", 0);
    return NULL;
  }

switch(flag) {
  case PBUF_POOL:
    /* Allocate head of pbuf chain into p. */
    p = pbuf_pool_alloc(); // 为PBUF_POOL类型,那么需要多申请pbuf的head控制头部所需内存[luther.gliethttp]
    if(p == NULL) {
#ifdef PBUF_STATS
      ++stats.pbuf.err;
#endif /* PBUF_STATS */
      return NULL;
    }
    p->next = NULL;
    
    /* Set the payload pointer so that it points offset bytes into
       pbuf data memory. */
    p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset))); // 以offset为基准,登记有效数据存储的起始偏移位置到p->payload[luther.gliethttp]

/* The total length of the pbuf is the requested size. */
    p->tot_len = size; // pbuf链表上有效数据总大小

/* Set the length of the first pbuf is the chain. */
    // pbuf链表上每个元素所能存储的最大数据为PBUF_POOL_BUFSIZE,如果超过该值,那么就会
    // 使用链表方式,链接其很多个pbuf,直到申请的size数据全部能够正常存储为止[luther.gliethttp]
    p->len = size > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: size;

p->flags = PBUF_FLAG_POOL;
    
    /* Allocate the tail of the pbuf chain. */
    r = p;
    rsize = size - p->len; // 第1个pbuf所能存储数据大小为p->len,这里计算还需要多少存储空间存储剩下的数据.
    while(rsize > 0) {     // 构成数据缓存链表,每个链表元素所能存储的最大数据量为PBUF_POOL_BUFSIZE个字节[luther.gliethttp]
      q = pbuf_pool_alloc();
      if(q == NULL) {
    DEBUGF(PBUF_DEBUG, ("pbuf_alloc: Out of pbufs in pool,\n"));
#ifdef PBUF_STATS
        ++stats.pbuf.err;
#endif /* PBUF_STATS */
        pbuf_pool_free(p);
        return NULL;
      }
      q->next = NULL;
      r->next = q;
      q->len = rsize > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rsize;
      q->flags = PBUF_FLAG_POOL;
      q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
      r = q;
      q->ref = 1;
      q = q->next;
      rsize -= PBUF_POOL_BUFSIZE;
    }
    r->next = NULL;

ASSERT("pbuf_alloc: pbuf->payload properly aligned",
       ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
    break;
  case PBUF_RAM:
    /* If pbuf is to be allocated in RAM, allocate memory for it. */
// PBUF_RAM类型内存,那么一次性申请size大小的连续内存
    p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + size + offset));
    if(p == NULL) {
      return NULL;
    }
    /* Set up internal structure of the pbuf. */
    p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));
    p->len = p->tot_len = size;
    p->next = NULL;
    p->flags = PBUF_FLAG_RAM;

ASSERT("pbuf_alloc: pbuf->payload properly aligned",
       ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
    break;
  case PBUF_ROM:
    /* If the pbuf should point to ROM, we only need to allocate
       memory for the pbuf structure. */
// PBUF_ROM类型内存,那么只需要申请pbufs头部控制结构体所需内存即可[luther.gliethttp]
    p = memp_mallocp(MEMP_PBUF);
    if(p == NULL) {
      return NULL;
    }
    p->payload = NULL;
    p->len = p->tot_len = size;
    p->next = NULL;
    p->flags = PBUF_FLAG_ROM;
    break;
  default:
    ASSERT("pbuf_alloc: erroneous flag", 0);
    return NULL;
  }
  p->ref = 1;
  return p;
}

关于lwip中pbuf_alloc()内存申请函数相关推荐

  1. Linux 基础知识(2)---Linux内核空间内存申请函数kmalloc、kzalloc、vmalloc的区别

    Linux内核空间内存申请函数kmalloc.kzalloc.vmalloc的区别 kzalloc与kmalloc区别    这个函数就是原来的两个函数的整合 , 即原来我们每次申请内存的时候都会这么 ...

  2. Linux内核空间内存申请函数kmalloc、kzalloc、vmalloc的区别

    Table of Contents kmalloc() kzalloc() vmalloc() 总结 内核中的内存申请:kmalloc.vmalloc.kzalloc.kcalloc.get_free ...

  3. linux 内核申请内存大小,linux内核常用的内存申请函数

    在读驱动程序时,常遇到内存申请函数.驱动程序属于内核空间,和用户空间用到的内存申请函数不同. 内核空间最常用到的内存申请函数为kmalloc()和kzalloc(). kmalloc()是申请一段内存 ...

  4. 替换libc中的内存分配函数

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 本文介绍如何替换glibc中的内存分配函数为自定义的内存分配函数的方法,可以方便调试内存分配,和查找内存管理错误而产生 ...

  5. C 中的内存操作函数-memcpy 等(to be continued)

    文章目录 C中的内存操作函数 1.memcpy() 1.1 函数介绍 1.2 示例代码 1.3 Reference C中的内存操作函数 1.memcpy() 1.1 函数介绍 void *memcpy ...

  6. 内核中的内存申请:kmalloc、vmalloc、kzalloc、kcalloc、get_free_pages【转】

    转自:http://www.cnblogs.com/yfz0/p/5829443.html 在内核模块中申请分配内存需要使用内核中的专用API:kmalloc.vmalloc.kzalloc.kcal ...

  7. linux 内核 内存申请函数 kmalloc、kzalloc、vmalloc 区别

    我们都知道在用户空间动态申请内存用的函数是 malloc(),这个函数在各种操作系统上的使用是一致的,对应的用户空间内存释放函数是 free().注意:动态申请的内存使用完后必须要释放,否则会造成内存 ...

  8. 内核中的内存申请:kmalloc、vmalloc、kzalloc、get_free_pages 之间的区别

    kmalloc   vmalloc   kzalloc   get_free_page()是内核空间申请内存空间函数 malloc是用户空间申请内存函数 一 ,kmalloc() 与 kfree()  ...

  9. Linux内核中常见内存分配函数

    1.      原理说明 Linux内核中采用了一种同时适用于32位和64位系统的内存分页模型,对于32位系统来说,两级页表足够用了,而在x86_64系统中,用到了四级页表,如图2-1所示.四级页表分 ...

最新文章

  1. img 服务器上的图片不显示图片,img显示服务器图片不显示
  2. Linux学习总结(3)——Linux实用工具
  3. MyEclipse10 Tomcat7 JDK1.7 配置
  4. 使用will和would来提出请求_42
  5. 华为云HCIE认证有多难?考试内容是什么?
  6. 简书的css排版,浅谈前端(WEB)排版
  7. NCURSES程序设计之魔数方阵
  8. 时域OCT(TD-OCT) 我的理解
  9. oracle使用decode实现竖表转横表 (列转行)
  10. excel输入公式不计算结果
  11. 多元函数的向量表示_多元高斯分布完全解析
  12. 匿名突破网络限制 (Tor工作原理分析)
  13. PHP中magic_quotes_gpc和magic_quotes_runtime的区别、作用和用法
  14. ‘SHIT’上最全有限状态机设计研究(一)-状态机介绍
  15. 国家名称映射和省市名称映射
  16. (C语言)栈应用简易计算器实现
  17. Simulink库大全
  18. 华为mpls实验 rip ospf sham-link
  19. python 什么值得买 签到_第一个实用python程序——自动填写工作日志、签到
  20. labview can通讯上位机,调用周立功库文件

热门文章

  1. Mozilla工程师观点:开源不赚钱,因为它不是为赚钱而设计的
  2. 【287】◀▶ arcpy 常用类说明
  3. DLT(Diagnostic Log and Trace)嵌入式系统程序运行记录
  4. 【转】Win8/8.1/Win7小技巧:揪出C盘空间占用的真凶
  5. 深入Java核心 Java内存分配原理精讲(3)
  6. URAL 1036 Lucky Tickets
  7. labview当前vi路径_对于LabVIEW程序为什么生成EXE后,涉及到路径的输出不正确了?...
  8. spring-security学习笔记--配置文件
  9. XML Schema全接触 (这里主要介绍W3C的Schema标准语法)
  10. java执行命令无返回_java运行cmd命令并获取返回信息的问题!!怎么不行了?