十四、Nginx的内存管理

  1. 内存池的逻辑结构:

    1. 链表1:多个分配模块,通过ngx_pool_data_t结构中的next成员,构成链表,形成内存池。

    2. 链表2:ngx_pool_large_t结构中的next成员,形成大数据内存块分配的链表。挂接在第一个分配模块上。

    3. 链表3:ngx_pool_cleanup_t结构中的next成员,形成内存回收链表。同样挂接第一个分配模块上。

  2. 内存池的管理:

    1. 相关源码位于:src/core/ngx_palloc.c文件中。

    2. 创建内存池:

      1. 按优先级选用如下三个系统调用,用于分配模块内存:

        1. posix_memalign(): 考虑数据对齐。

        2. memalign(): 考虑数据对齐。

        3. malloc(): 不考虑数据对齐。

      2. ngx_pool_t结构中的max成员:

        1. 含义:表示该分配模块可用于分配的最大内存。

        2. 源码疑问1:

          1. 源码:p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;

          2. 疑问:p->max的值应该为分配模块的大小size减去ngx_pool_t结构的大小。???

      3. 示例:

        1. 源码:init_cycle.pool = ngx_pool_create(1024, log); // 假设内存起始地址从10开始。

    3. 销毁内存池:

      1. 处理过程:

        1. 遍历ngx_pool_cleanup_t链表,调用各个节点的回调函数,进行数据清除操作。

        2. 遍历ngx_pool_large_t链表,释放各个节点上挂接的内存。

        3. 遍历ngx_pool_t链表,释放各个分配模块。

      2. 从处理过程中可以看出,ngx_pool_cleanup_t链表和ngx_pool_large_t链表只在第一个ngx_pool_t结构中存在。???

    4. 重置内存池:

      1. 处理过程:

        1. 遍历ngx_pool_large_t链表,释放各个节点上挂接的内存。

        2. 遍历ngx_pool_t链表,将各个分配模块的last指针重置到刚分配时的位置。

  3. 内存的使用:

    1. 申请内存:

      1. Nginx内存池中申请内存的函数有3个:ngx_palloc(), ngx_pnalloc()和ngx_calloc()。

      2. ngx_palloc()源码分析:

        1. 如果申请的内存大小size小于等于pool->max,则ngx_palloc_small()分配内存:

          1. 在当前分配模块pool中,判断pool->d.last + size是否小于pool->d.end,如果小于则在该分配模块分配内存,否则通过pool->d.next,在下一个分配模块中申请内存。

          2. 如果ngx_pool_t链表中没有剩余内存可供分配,则使用ngx_palloc_block()在系统内存中申请新的分配模块:

            1. 在系统内存中申请新的分配模块ngx_pool_t,并进行初始化。

            2. 在分配模块上分配所需的内存大小。

            3. 将新的分配模块,添加到ngx_pool_t链表上:

              1. 注意:ngx_pool_t结构中的current指针成员是会移动的。

              2. pool->current指向ngx_pool_t链表的某个节点,该节点是所有链表节点中ngx_pool_data_t结构中failed成员最后一个小于等于4的节点。

              3. 将新的分配模块添加到ngx_pool_t链表的末尾。

        2. 否则使用ngx_palloc_large()申请大数据块内存。

          1. 使用ngx_alloc(实际使用了系统调用malloc),申请大数据块内存。

          2. 遍历ngx_pool_large_t链表,将新申请的内存挂接在合适的节点上。

          3. 如果没有合适的节点,则创建新的ngx_pool_large_t结构来挂接大数据块内存,并将新创建的结构插入到ngx_pool_large_t链表开头。

      3. ngx_pnalloc()源码分析:

        1. 与ngx_palloc()功能基本相同,只是在分配内存时,没有考虑数据对齐的问题。

      4. ngx_pcalloc()源码分析:

        1. 与ngx_palloc()功能基本相同,只是在分配内存后,将内存中的数据清零。

      5. ngx_calloc()源码分析:

        1. 位于:src/os/unix/ngx_alloc.c文件中。

        2. 功能:从系统内存(而非内存池中分配内存)中分配内存,并初始化。

    2. 释放内存:

      1. 源码:#define  ngx_free free

      2. 说明:大数据块内存交由ngx_free()进行释放,其他内存交由内存池的销毁过程。

    3. 回收内存:

      1. 原因:某些数据类型在回收其所占用的内存空间时,在释放内存空间前,还需要进行指定的清理操作。

      2. 处理:清理函数和待清理的数据,分别存储在ngx_pool_cleanup_s结构的handle和data成员中。

  4. 总结:

    1. 在内存池链表上通过ngx_palloc()申请的内存,不能被单独释放。

    2. 内存池链表是随着内存申请而逐渐增加的。

    3. 内存池链表只能整体释放或重置。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值