Ningx代码研究(二)

系统 1872 0

内存分配相关

系统功能封装

内存相关的操作主要在 os/unix/ngx_alloc.{h,c} 和 core/ngx_palloc.{h,c} 下

其中 os/unix/ngx_alloc.{h,c} 封装了最基本的内存分配函数,是对c原有的malloc/free/memalign 等原有的函数的封装,对应的函数为:

  • ngx_alloc 使用malloc分配内存空间
  • ngx_calloc 使用malloc分配内存空间,并且将空间内容初始化为0
  • ngx_memalign 返回基于一个指定的alignment大小的数值为对齐基数的空间
  • ngx_free 对内存的释放操作

ngx的内存池

为了方便系统模块对内存的使用,方便内存的管理,nginx自己实现了进程池的机制来进行内存的分配和释放, 首先nginx会在特定的生命周期帮你统一建立内存池,当需要进行内存分配的时候统一通过内存池中的内存进行分配,最后nginx会在适当的时候释放内存池的资源,开发者只要在需要的时候对内存进行申请即可,不用过多考虑内存的释放等问题,大大提高了开发的效率。

内存池的主要结构为:

    
      //ngx_palloc.h
    
    
    
    
      struct
    
    
       ngx_pool_s 
    
    
      {
    
    
      
    ngx_pool_data_t       d
    
    
      ;
    
    
      
    size_t                max
    
    
      ;
    
    
      
    ngx_pool_t           
    
    
      *
    
    
      current
    
    
      ;
    
    
      
    ngx_chain_t          
    
    
      *
    
    
      chain
    
    
      ;
    
    
      
    ngx_pool_large_t     
    
    
      *
    
    
      large
    
    
      ;
    
    
      
    ngx_pool_cleanup_t   
    
    
      *
    
    
      cleanup
    
    
      ;
    
    
      
    ngx_log_t            
    
    
      *
    
    
      log
    
    
      ;
    
    
    
    
      };
    
    
    
    
      //ngx_core.h
    
    
    
    
      typedef
    
    
    
    
      struct
    
    
       ngx_pool_s        ngx_pool_t
    
    
      ;
    
    
    
    
      typedef
    
    
    
    
      struct
    
    
       ngx_chain_s       ngx_chain_t
    
    
      ;
    
  

下面是我简单画的一个图来描述这个结构:

link :  http://www.flickr.com/photos/rainx/3765612584/sizes/o/

下面解释一下主要的几个操作:

    
      // 创建内存池
    
    
      
ngx_pool_t 
    
    
      *
    
    
      ngx_create_pool
    
    
      (
    
    
      size_t size
    
    
      ,
    
    
       ngx_log_t 
    
    
      *
    
    
      log
    
    
      );
    
  

大致的过程是创建使用 ngx_alloc 分配一个size大小的空间, 然后将  ngx_pool_t*  指向这个空间, 并且初始化里面的成员, 其中

    
      p
    
    
      ->
    
    
      d
    
    
      .
    
    
      last
    
    
    
    
      =
    
    
    
    
      (
    
    
      u_char 
    
    
      *)
    
    
       p 
    
    
      +
    
    
    
    
      sizeof
    
    
      (
    
    
      ngx_pool_t
    
    
      );
    
    
    
    
      // 初始指向 ngx_pool_t 结构体后面
    
    
      
p
    
    
      ->
    
    
      d
    
    
      .
    
    
      end
    
    
    
    
      =
    
    
    
    
      (
    
    
      u_char 
    
    
      *)
    
    
       p 
    
    
      +
    
    
       size
    
    
      ;
    
    
    
    
      // 整个结构的结尾后面
    
    
      
p
    
    
      ->
    
    
      max 
    
    
      =
    
    
    
    
      (
    
    
      size 
    
    
      <
    
    
       NGX_MAX_ALLOC_FROM_POOL
    
    
      )
    
    
    
    
      ?
    
    
       size 
    
    
      :
    
    
       NGX_MAX_ALLOC_FROM_POOL
    
    
      ;
    
    
    
    
      // 最大不超过 NGX_MAX_ALLOC_FROM_POOL,也就是getpagesize()-1 大小
    
  

其他大都设置为null或者0

    
      // 销毁内存池
    
    
    
    
      void
    
    
       ngx_destroy_pool
    
    
      (
    
    
      ngx_pool_t 
    
    
      *
    
    
      pool
    
    
      );
    
  

遍历链表,所有释放内存,其中如果注册了clenup(也是一个链表结构), 会一次调用clenup 的 handler 进行清理。

    
      // 重置内存池
    
    
    
    
      void
    
    
       ngx_reset_pool
    
    
      (
    
    
      ngx_pool_t 
    
    
      *
    
    
      pool
    
    
      );
    
  

释放所有large段内存, 并且将d->last指针重新指向 ngx_pool_t 结构之后(和创建时一样)

    
      // 从内存池里分配内存
    
    
    
    
      void
    
    
    
    
      *
    
    
      ngx_palloc
    
    
      (
    
    
      ngx_pool_t 
    
    
      *
    
    
      pool
    
    
      ,
    
    
       size_t size
    
    
      );
    
    
    
    
      void
    
    
    
    
      *
    
    
      ngx_pnalloc
    
    
      (
    
    
      ngx_pool_t 
    
    
      *
    
    
      pool
    
    
      ,
    
    
       size_t size
    
    
      );
    
    
    
    
      void
    
    
    
    
      *
    
    
      ngx_pcalloc
    
    
      (
    
    
      ngx_pool_t 
    
    
      *
    
    
      pool
    
    
      ,
    
    
       size_t size
    
    
      );
    
    
    
    
      void
    
    
    
    
      *
    
    
      ngx_pmemalign
    
    
      (
    
    
      ngx_pool_t 
    
    
      *
    
    
      pool
    
    
      ,
    
    
       size_t size
    
    
      ,
    
    
       size_t alignment
    
    
      );
    
  

ngx_palloc的过程一般为,首先判断待分配的内存是否大于 pool->max的大小,如果大于则使用 ngx_palloc_large 在 large 链表里分配一段内存并返回, 如果小于测尝试从链表的 pool->current 开始遍历链表,尝试找出一个可以分配的内存,当链表里的任何一个节点都无法分配内存的时候,就调用 ngx_palloc_block 生成链表里一个新的节点, 并在新的节点里分配内存并返回, 同时, 还会将pool->current 指针指向新的位置(从链表里面pool->d.failed小于等于4的节点里找出) ,其他几个函数也基本上为 ngx_palloc 的变种,实现方式大同小异

    
      // 释放指定的内存
    
    
      
ngx_int_t ngx_pfree
    
    
      (
    
    
      ngx_pool_t 
    
    
      *
    
    
      pool
    
    
      ,
    
    
    
    
      void
    
    
    
    
      *
    
    
      p
    
    
      );
    
  

这个操作只有在内存在large链表里注册的内存在会被真正释放,如果分配的是普通的内存,则会在destory_pool的时候统一释放.

    
      // 注册cleanup回叫函数(结构体)
    
    
      
ngx_pool_cleanup_t 
    
    
      *
    
    
      ngx_pool_cleanup_add
    
    
      (
    
    
      ngx_pool_t 
    
    
      *
    
    
      p
    
    
      ,
    
    
       size_t size
    
    
      );
    
  

这个过程和我们之前经常使用的有些区别, 他首先在传入的内存池中分配这个结构的空间(包括data段), 然后将为结构体分配的空间返回, 通过操作返回的ngx_pool_cleanup_t结构来添加回叫的实现。 ( 这个过程在nginx里面出现的比较多,也就是 xxxx_add 操作通常不是实际的添加操作,而是分配空间并返回一个指针,后续我们还要通过操作指针指向的空间来实现所谓的add )

下面是内存操作的一些例子 demo/basic_types/mem_op.c

    
      #include
    
    
    
    
      <stdio.h>
    
    
    
    
      #include
    
    
    
    
      "ngx_config.h"
    
    
    
    
      #include
    
    
    
    
      "ngx_conf_file.h"
    
    
    
    
      #include
    
    
    
    
      "nginx.h"
    
    
    
    
      #include
    
    
    
    
      "ngx_core.h"
    
    
    
    
      #include
    
    
    
    
      "ngx_string.h"
    
    
    
    
      #include
    
    
    
    
      "ngx_palloc.h"
    
    
    
    
      volatile
    
    
       ngx_cycle_t  
    
    
      *
    
    
      ngx_cycle
    
    
      ;
    
    
    
    
      void
    
    
      
ngx_log_error_core
    
    
      (
    
    
      ngx_uint_t level
    
    
      ,
    
    
       ngx_log_t 
    
    
      *
    
    
      log
    
    
      ,
    
    
       ngx_err_t err
    
    
      ,
    
    
      
            
    
    
      const
    
    
    
    
      char
    
    
    
    
      *
    
    
      fmt
    
    
      ,
    
    
    
    
      ...)
    
    
    
    
      {
    
    
    
    
      }
    
    
    
    
      typedef
    
    
    
    
      struct
    
    
       example_s 
    
    
      {
    
    
      
    
    
    
      int
    
    
       a
    
    
      ;
    
    
      
    
    
    
      char
    
    
      *
    
    
       b
    
    
      ;
    
    
    
    
      }
    
    
       example_t
    
    
      ;
    
    
    
    
      int
    
    
       main
    
    
      ()
    
    
    
    
      {
    
    
      
    ngx_pool_t 
    
    
      *
    
    
      pool
    
    
      ;
    
    
      
    example_t
    
    
      *
    
    
       exp
    
    
      ;
    
    
      
    
    
    
      char
    
    
      *
    
    
       s
    
    
      ;
    
    
      

    pool 
    
    
      =
    
    
       ngx_create_pool
    
    
      (
    
    
      5000
    
    
      ,
    
    
       NULL
    
    
      );
    
    
      
    printf
    
    
      (
    
    
      "available pool regular pool free size is %d now\n"
    
    
      ,
    
    
    
    
      (
    
    
      ngx_uint_t
    
    
      )
    
    
    
    
      (
    
    
      pool
    
    
      ->
    
    
      d
    
    
      .
    
    
      end
    
    
    
    
      -
    
    
       pool
    
    
      ->
    
    
      d
    
    
      .
    
    
      last
    
    
      ));
    
    
      
    exp 
    
    
      =
    
    
       ngx_palloc
    
    
      (
    
    
      pool
    
    
      ,
    
    
    
    
      sizeof
    
    
      (
    
    
      example_t
    
    
      ))
    
    
    
    
      ;
    
    
      
    s 
    
    
      =
    
    
       ngx_palloc
    
    
      (
    
    
      pool
    
    
      ,
    
    
    
    
      sizeof
    
    
      (
    
    
      "hello,world"
    
    
      ));
    
    
      
    printf
    
    
      (
    
    
      "available pool regular pool free size is %d now\n"
    
    
      ,
    
    
    
    
      (
    
    
      ngx_uint_t
    
    
      )
    
    
    
    
      (
    
    
      pool
    
    
      ->
    
    
      d
    
    
      .
    
    
      end
    
    
    
    
      -
    
    
       pool
    
    
      ->
    
    
      d
    
    
      .
    
    
      last
    
    
      ));
    
    
      
    exp
    
    
      ->
    
    
      a 
    
    
      =
    
    
    
    
      1
    
    
      ;
    
    
      
    exp
    
    
      ->
    
    
      b 
    
    
      =
    
    
       s
    
    
      ;
    
    
      
    strcpy
    
    
      (
    
    
      s
    
    
      ,
    
    
    
    
      "hello,world"
    
    
      );
    
    
      
    printf
    
    
      (
    
    
      "pool max is %d\n"
    
    
      ,
    
    
       pool
    
    
      ->
    
    
      max
    
    
      );
    
    
      
    printf
    
    
      (
    
    
      "exp->a is %d, exp->b is %s\n"
    
    
      ,
    
    
       exp
    
    
      ->
    
    
      a
    
    
      ,
    
    
       exp
    
    
      ->
    
    
      b
    
    
      );
    
    
      
    ngx_destroy_pool
    
    
      (
    
    
      pool
    
    
      );
    
    
      
    
    
    
      return
    
    
    
    
      0
    
    
      ;
    
    
    
    
      }
    
  

编译运行结果

    
      gcc  
    
    
      -
    
    
      c 
    
    
      -
    
    
      O 
    
    
      -
    
    
      pipe  
    
    
      -
    
    
      O 
    
    
      -
    
    
      W 
    
    
      -
    
    
      Wall
    
    
    
    
      -
    
    
      Wpointer
    
    
      -
    
    
      arith 
    
    
      -
    
    
      Wno
    
    
      -
    
    
      unused
    
    
      -
    
    
      parameter 
    
    
      -
    
    
      Wunused
    
    
      -
    
    
      function
    
    
    
    
      -
    
    
      Wunused
    
    
      -
    
    
      variable 
    
    
      -
    
    
      Wunused
    
    
      -
    
    
      value 
    
    
      -
    
    
      Werror
    
    
    
    
      -
    
    
      g 
    
    
      -
    
    
      I 
    
    
      ../../../
    
    
      objs
    
    
      /
    
    
    
    
      -
    
    
      I 
    
    
      ../../
    
    
      os
    
    
      /
    
    
      unix
    
    
      /
    
    
       mem_op
    
    
      .
    
    
      c 
    
    
      -
    
    
      I
    
    
      ../../
    
    
      core
    
    
      /
    
    
    
    
      -
    
    
      I
    
    
      ../../
    
    
      event
    
    
      /
    
    
    
    
      -
    
    
      I
    
    
      ../../
    
    
      os
    
    
      /
    
    
    
    
      -
    
    
      o mem_op
    
    
      .
    
    
      o
 gcc 
    
    
      -
    
    
      o mem_op mem_op
    
    
      .
    
    
      o 
    
    
      ../../../
    
    
      objs
    
    
      /
    
    
      src
    
    
      /
    
    
      core
    
    
      /
    
    
      ngx_
    
    
      {
    
    
      string
    
    
      ,
    
    
      palloc
    
    
      }.
    
    
      o 
    
    
      ../../../
    
    
      objs
    
    
      /
    
    
      src
    
    
      /
    
    
      os
    
    
      /
    
    
      unix
    
    
      /
    
    
      ngx_alloc
    
    
      .
    
    
      o 
    
    
      -
    
    
      lcrypt 
    
    
      -
    
    
      lpcre 
    
    
      -
    
    
      lcrypto 
    
    
      -
    
    
      lz
rainx@rainx
    
    
      -
    
    
      laptop
    
    
      :~/
    
    
      land
    
    
      /
    
    
      nginx
    
    
      -
    
    
      0.7
    
    
      .
    
    
      61
    
    
      /
    
    
      src
    
    
      /
    
    
      demo
    
    
      /
    
    
      basic_types$ 
    
    
      ./
    
    
      mem_op 
available pool regular pool free size 
    
    
      is
    
    
    
    
      4960
    
    
       now
available pool regular pool free size 
    
    
      is
    
    
    
    
      4940
    
    
       now
pool max 
    
    
      is
    
    
    
    
      4960
    
    
      
exp
    
    
      ->
    
    
      a 
    
    
      is
    
    
    
    
      1
    
    
      ,
    
    
       exp
    
    
      ->
    
    
      b 
    
    
      is
    
    
       hello
    
    
      ,
    
    
      world
    
  

Ningx代码研究(二)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论