zoukankan      html  css  js  c++  java
  • Nginx 源码分析 内存池(pool)的分析 二

      在上一篇中,以一张图(图1)介绍了nginx内存池管理函数的总体概况,并分析了底层支持函数和内存池(pool)管理所需要用到的一些数据结构。这里我们将来具体分析内存池管理功能函数。由上篇图1我们可以看出ngx_palloc为内存分配的核心,为此我们先看看这个函数。

    void *   ngx_palloc(ngx_pool_t *pool, size_t size)
    {
        u_char      *m;
        ngx_pool_t  *p;
      /*
        注意2个if,3个return
      */
    if (size <= pool->max) { p = pool->current; do { m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT); if ((size_t) (p->d.end - m) >= size) { p->d.last = m + size; return m; } p = p->d.next; } while (p); return ngx_palloc_block(pool, size); } return ngx_palloc_large(pool, size); }

      函数结构很明晰,2个if,1个do...while循环查找,3个return,就此我们可以得出Nginx内存分配时会出现三种情况。

      第一,size <= pool->max 即所需要提供分配的内存小于Nginx内存池 pool允许容纳的最大值,那么这个时候开始顺着内存池pool的链表找,找着了能够分配需要大小size的内存空间,修改这个pool使用的内存尾指针last,并返回分配内存的首地址m。

      第二,size <= pool->max 但是查找发现当前存在的内存池pool链表里的pool单元都没有足够的内存分配,那么调用 ngx_palloc_block(pool, size),我们这里就可以看出来ngx_palloc_block 函数是用来产生新的pool单元。

      第三,如果size > pool->max,即所需要的提供分配的内存大于Nginx内存池 pool允许容纳的最大值,这说明即使生成新的pool单元也无法分配出这么大的需求,那么调用 ngx_palloc_large(pool, size)进行大内存单元分配。

      因为,ngx_palloc是内存池分配的核心函数,为了更便于理解,罗嗦一下再附上张简单的示意图:

    pool_alloc示意图

    图2 pool_alloc示意图

      了解ngx_palloc功能的流程后,我们可以发现ngx_palloc由ngx_palloc_block 和  ngx_palloc_large 两大支柱函数来完成些它无法完成的功能。查看ngx_palloc_block 源码,和我们先前分析出来的一样构造一个新的pool单元并记录下内存池分配失败的次数, ngx_palloc_large 用ngx_pool_large_t 结构体来对大内存需要分配内存,值得注意的是每个ngx_pool_large_t链表只能允许4个ngx_pool_large_t,如果超过4个大块内存分配请求,就会建造新的ngx_pool_large_t资源链表。详情见源码

    static void * ngx_palloc_large(ngx_pool_t *pool, size_t size)
    {
        void              *p;
        ngx_uint_t         n;
        ngx_pool_large_t  *large;
      /*分配大块内存*/
        p = ngx_alloc(size, pool->log);
        if (p == NULL) {
            return NULL;
        }
    
        n = 0;
        for (large = pool->large; large; large = large->next) {
            if (large->alloc == NULL) {
                large->alloc = p;
                return p;
            }
       /*链表不能超过四个*/
            if (n++ > 3) {
                break;
            }
        }
      /*新的大内存块链块*/
        large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
        if (large == NULL) {
            ngx_free(p);
            return NULL;
        }
        large->alloc = p;
        large->next = pool->large;
        pool->large = large;
        return p;
    }

      此篇就分析到此处。

    欢迎关注 公众号
  • 相关阅读:
    (转)一篇教会你写90%的shell脚本
    (转)printf命令详解
    (转)linux shell 字符串操作详解 (长度,读取,替换,截取,连接,对比,删除,位置 )
    (转)Shell中read的选项及用法
    (转)linux中shell变量$#,$@,$0,$1,$2的含义解释/Shell中的${}、##和%%使用范例/export
    (转)linux运维人员必会的22道shell编程面试题及视频讲解
    (转)李文周的博客
    ROS报错“An error occurred during the signature verification”的解决办法
    RRT and RRT Variants
    ROS LocalPlanner 基于自行车模型的DWA
  • 原文地址:https://www.cnblogs.com/jzhlin/p/2537710.html
Copyright © 2011-2022 走看看