日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Ningx代碼研究(二)

系統 2198 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條評論
主站蜘蛛池模板: 罗甸县| 静乐县| 泰安市| 旺苍县| 恩平市| 黄大仙区| 阳西县| 峨眉山市| 资阳市| 临清市| 阿城市| 霍林郭勒市| 安庆市| 兰坪| 治县。| 樟树市| 精河县| 临沧市| 苏尼特左旗| 新竹市| 江华| 汝城县| 察哈| 平乐县| 龙江县| 金沙县| 四子王旗| 昭平县| 马山县| 麟游县| 云和县| 怀化市| 淮滨县| 岳阳市| 阿拉善盟| 隆德县| 景洪市| 横峰县| 岗巴县| 江安县| 宁海县|