Ningx代码研究(四)

系统 1597 0

虽然代码理解起来比较混乱,但是使用还是比较简单的,常用的有创建 hash 和在 hash 中进行查找两个操作,对于创建hash的操作,过程一般为:

  1. 构造一个 ngx_hash_key_t 为成员的数组, 包含 key, value 和 使用key计算出的一个hash值
  2. 构建一个 ngx_hash_init_t结构体的变量, 其中包含了ngx_hash_t 的成员, 为hash的结构体, 还包括一些其他初始设置,如bucket的大小,内存池等
  3. 调用 ngx_hash_init 传入 ngx_hash_init_t 结构, ngx_hash_key_t 的数组,和数组的长度, 进行初始化,这样 ngx_hash_init_t的hash成员就是我们要的hash结构

查找的过程很简单

  1. 计算 key 的hash值
  2. 使用 ngx_hash_find 进行查找,需要同时传入 hash值和key ,返回的就是value的指针

 

需要注意的是,nginx 的 hash 在查找时使用的是分桶后线性查找法,因此当分桶数确定时查找效率同其中的总 key-val 对数量成反比。

下面是一些demo代码(可以从svn中找到)

    
      #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"
    
    
    
    
      #include
    
    
    
    
      "ngx_array.h"
    
    
    
    
      #include
    
    
    
    
      "ngx_hash.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
    
    
      ,
    
    
    
    
      ...)
    
    
    
    
      {
    
    
    
    
      }
    
    
    
    
      static
    
    
       ngx_str_t names
    
    
      []
    
    
    
    
      =
    
    
    
    
      {
    
    
      ngx_string
    
    
      (
    
    
      "rainx"
    
    
      ),
    
    
      
                            ngx_string
    
    
      (
    
    
      "xiaozhe"
    
    
      ),
    
    
      
                            ngx_string
    
    
      (
    
    
      "zhoujian"
    
    
      )};
    
    
    
    
      static
    
    
    
    
      char
    
    
      *
    
    
       descs
    
    
      []
    
    
    
    
      =
    
    
    
    
      {
    
    
      "rainx's id is 1"
    
    
      ,
    
    
      "xiaozhe's id is 2"
    
    
      ,
    
    
      "zhoujian's id is 3"
    
    
      };
    
    
    
    
      // hash table的一些基本操作
    
    
    
    
      int
    
    
       main
    
    
      ()
    
    
    
    
      {
    
    
      
    ngx_uint_t          k
    
    
      ;
    
    
    
    
      //, p, h;
    
    
      
    ngx_pool_t
    
    
      *
    
    
               pool
    
    
      ;
    
    
      
    ngx_hash_init_t     hash_init
    
    
      ;
    
    
      
    ngx_hash_t
    
    
      *
    
    
               hash
    
    
      ;
    
    
      
    ngx_array_t
    
    
      *
    
    
              elements
    
    
      ;
    
    
      
    ngx_hash_key_t
    
    
      *
    
    
           arr_node
    
    
      ;
    
    
      
    
    
    
      char
    
    
      *
    
    
                     find
    
    
      ;
    
    
      
    
    
    
      int
    
    
                       i
    
    
      ;
    
    
      

    ngx_cacheline_size 
    
    
      =
    
    
    
    
      32
    
    
      ;
    
    
      
    
    
    
      // hash key cal start
    
    
      
    ngx_str_t str       
    
    
      =
    
    
       ngx_string
    
    
      (
    
    
      "hello, world"
    
    
      );
    
    
      
    k                   
    
    
      =
    
    
       ngx_hash_key_lc
    
    
      (
    
    
       str
    
    
      .
    
    
      data
    
    
      ,
    
    
       str
    
    
      .
    
    
      len
    
    
      );
    
    
      
    pool                
    
    
      =
    
    
       ngx_create_pool
    
    
      (
    
    
      1024
    
    
      *
    
    
      10
    
    
      ,
    
    
       NULL
    
    
      );
    
    
      
    printf
    
    
      (
    
    
      "caculated key is %u \n"
    
    
      ,
    
    
       k
    
    
      );
    
    
      
    
    
    
      // hask key cal end
    
    
      
    
    
    
      //
    
    
      
    hash 
    
    
      =
    
    
    
    
      (
    
    
      ngx_hash_t
    
    
      *)
    
    
       ngx_pcalloc
    
    
      (
    
    
      pool
    
    
      ,
    
    
    
    
      sizeof
    
    
      (
    
    
      hash
    
    
      ));
    
    
      
    hash_init
    
    
      .
    
    
      hash      
    
    
      =
    
    
       hash
    
    
      ;
    
    
                            
    
    
      // hash结构
    
    
      
    hash_init
    
    
      .
    
    
      key       
    
    
      =
    
    
    
    
      &
    
    
      ngx_hash_key_lc
    
    
      ;
    
    
                
    
    
      // hash算法函数
    
    
      
    hash_init
    
    
      .
    
    
      max_size  
    
    
      =
    
    
    
    
      1024
    
    
      *
    
    
      10
    
    
      ;
    
    
                         
    
    
      // max_size
    
    
      
    hash_init
    
    
      .
    
    
      bucket_size 
    
    
      =
    
    
    
    
      64
    
    
      ;
    
    
    
    
      // ngx_align(64, ngx_cacheline_size);
    
    
      
    hash_init
    
    
      .
    
    
      name      
    
    
      =
    
    
    
    
      "yahoo_guy_hash"
    
    
      ;
    
    
                
    
    
      // 在log里会用到
    
    
      
    hash_init
    
    
      .
    
    
      pool           
    
    
      =
    
    
       pool
    
    
      ;
    
    
                       
    
    
      // 内存池
    
    
      
    hash_init
    
    
      .
    
    
      temp_pool      
    
    
      =
    
    
       NULL
    
    
      ;
    
    
      

    
    
    
      // 创建数组
    
    
      

    elements 
    
    
      =
    
    
       ngx_array_create
    
    
      (
    
    
      pool
    
    
      ,
    
    
    
    
      32
    
    
      ,
    
    
    
    
      sizeof
    
    
      (
    
    
      ngx_hash_key_t
    
    
      ));
    
    
      
    
    
    
      for
    
    
      (
    
    
      i 
    
    
      =
    
    
    
    
      0
    
    
      ;
    
    
       i 
    
    
      <
    
    
    
    
      3
    
    
      ;
    
    
       i
    
    
      ++)
    
    
    
    
      {
    
    
      
        arr_node            
    
    
      =
    
    
    
    
      (
    
    
      ngx_hash_key_t
    
    
      *)
    
    
       ngx_array_push
    
    
      (
    
    
      elements
    
    
      );
    
    
      
        arr_node
    
    
      ->
    
    
      key       
    
    
      =
    
    
    
    
      (
    
    
      names
    
    
      [
    
    
      i
    
    
      ]);
    
    
      
        arr_node
    
    
      ->
    
    
      key_hash  
    
    
      =
    
    
       ngx_hash_key_lc
    
    
      (
    
    
      arr_node
    
    
      ->
    
    
      key
    
    
      .
    
    
      data
    
    
      ,
    
    
       arr_node
    
    
      ->
    
    
      key
    
    
      .
    
    
      len
    
    
      );
    
    
      
        arr_node
    
    
      ->
    
    
      value     
    
    
      =
    
    
    
    
      (
    
    
      void
    
    
      *)
    
    
       descs
    
    
      [
    
    
      i
    
    
      ];
    
    
      
        
    
    
      // 
    
    
      
        printf
    
    
      (
    
    
      "key: %s , key_hash: %u\n"
    
    
      ,
    
    
       arr_node
    
    
      ->
    
    
      key
    
    
      .
    
    
      data
    
    
      ,
    
    
       arr_node
    
    
      ->
    
    
      key_hash
    
    
      );
    
    
      
    
    
    
      }
    
    
      

    
    
    
      if
    
    
    
    
      (
    
    
      ngx_hash_init
    
    
      (&
    
    
      hash_init
    
    
      ,
    
    
    
    
      (
    
    
      ngx_hash_key_t
    
    
      *)
    
    
       elements
    
    
      ->
    
    
      elts
    
    
      ,
    
    
       elements
    
    
      ->
    
    
      nelts
    
    
      )!=
    
    
      NGX_OK
    
    
      ){
    
    
      
        
    
    
      return
    
    
    
    
      1
    
    
      ;
    
    
      
    
    
    
      }
    
    
      

    
    
    
      // 查找
    
    
      
    k    
    
    
      =
    
    
       ngx_hash_key_lc
    
    
      (
    
    
      names
    
    
      [
    
    
      0
    
    
      ].
    
    
      data
    
    
      ,
    
    
       names
    
    
      [
    
    
      0
    
    
      ].
    
    
      len
    
    
      );
    
    
      
    printf
    
    
      (
    
    
      "%s key is %d\n"
    
    
      ,
    
    
       names
    
    
      [
    
    
      0
    
    
      ].
    
    
      data
    
    
      ,
    
    
       k
    
    
      );
    
    
      
    find 
    
    
      =
    
    
    
    
      (
    
    
      char
    
    
      *)
    
    
      
        ngx_hash_find
    
    
      (
    
    
      hash
    
    
      ,
    
    
       k
    
    
      ,
    
    
    
    
      (
    
    
      u_char
    
    
      *)
    
    
       names
    
    
      [
    
    
      0
    
    
      ].
    
    
      data
    
    
      ,
    
    
       names
    
    
      [
    
    
      0
    
    
      ].
    
    
      len
    
    
      );
    
    
      

    
    
    
      if
    
    
    
    
      (
    
    
      find
    
    
      )
    
    
    
    
      {
    
    
      
        printf
    
    
      (
    
    
      "get desc of rainx: %s\n"
    
    
      ,
    
    
    
    
      (
    
    
      char
    
    
      *)
    
    
       find
    
    
      );
    
    
      
    
    
    
      }
    
    
      

    ngx_array_destroy
    
    
      (
    
    
      elements
    
    
      );
    
    
      
    ngx_destroy_pool
    
    
      (
    
    
      pool
    
    
      );
    
    
      

    
    
    
      return
    
    
    
    
      0
    
    
      ;
    
    
    
    
      }
    
  

运行结果

    
      rainx@rainx
    
    
      -
    
    
      laptop
    
    
      :~/
    
    
      land
    
    
      /
    
    
      nginxsrp
    
    
      /
    
    
      src
    
    
      /
    
    
      demo
    
    
      /
    
    
      basic_types$ 
    
    
      ./
    
    
      hash_op 
caculated key 
    
    
      is
    
    
    
    
      3654358412
    
    
       
key
    
    
      :
    
    
       rainx 
    
    
      ,
    
    
       key_hash
    
    
      :
    
    
    
    
      108275556
    
    
      
key
    
    
      :
    
    
       xiaozhe 
    
    
      ,
    
    
       key_hash
    
    
      :
    
    
    
    
      2225329080
    
    
      
key
    
    
      :
    
    
       zhoujian 
    
    
      ,
    
    
       key_hash
    
    
      :
    
    
    
    
      3269715264
    
    
      
rainx key 
    
    
      is
    
    
    
    
      108275556
    
    
    
    
      get
    
    
       desc of rainx
    
    
      :
    
    
       rainx
    
    
      's id is 1
    
  

ngx_list

ngx_list 的结构并不复杂,ngx为我们封装了ngx_list_create, ngx_list_init, 和 ngx_list_push等(建立,初始化,添加)操作, 但是对于我们来说最常用的是遍历操作, 下面是nginx的注释里面提到的遍历的例子

    
         part 
    
    
      =
    
    
    
    
      &
    
    
      list
    
    
      .
    
    
      part
    
    
      ;
    
    
      
   data 
    
    
      =
    
    
       part
    
    
      ->
    
    
      elts
    
    
      ;
    
    
      
 
   
    
    
      for
    
    
    
    
      (
    
    
      i 
    
    
      =
    
    
    
    
      0
    
    
    
    
      ;;
    
    
       i
    
    
      ++)
    
    
    
    
      {
    
    
      
 
       
    
    
      if
    
    
    
    
      (
    
    
      i 
    
    
      >=
    
    
       part
    
    
      ->
    
    
      nelts
    
    
      )
    
    
    
    
      {
    
    
      
           
    
    
      if
    
    
    
    
      (
    
    
      part
    
    
      ->
    
    
      next
    
    
    
    
      ==
    
    
       NULL
    
    
      )
    
    
    
    
      {
    
    
      
               
    
    
      break
    
    
      ;
    
    
      
           
    
    
      }
    
    
      
 
           part 
    
    
      =
    
    
       part
    
    
      ->
    
    
      next
    
    
      ;
    
    
      
           data 
    
    
      =
    
    
       part
    
    
      ->
    
    
      elts
    
    
      ;
    
    
      
           i 
    
    
      =
    
    
    
    
      0
    
    
      ;
    
    
      
       
    
    
      }
    
    
      
 
       
    
    
      ...
    
    
        data
    
    
      [
    
    
      i
    
    
      ]
    
    
    
    
      ...
    
    
      
 
   
    
    
      }
    
  

了解nginx的core module 的结构和运行机制

参考资料

在开始这个task的学习的时候,经过搜索发现了langwan同学之前对nginx的源代码研究资料,很有参考意义,所以大量节省了我们的工作,我觉得对于本章的进行比较有用的是,下面这几个文章

  1. nginx源代码分析  http://hi.baidu.com/langwan/blog/item/6b18ef24cd859e064c088d28.html
  2. nginx 缓冲区构造  http://hi.baidu.com/langwan/blog/item/822b758d5d1d9a1ab31bbaf8.html
  3. Nginx源代码分析 - 日志处理  http://hi.baidu.com/langwan/blog/item/7e7db51978e04e4d43a9ad32.html

Debug信息的输出

为了方便研究,将nginx的debug 信息打开,重新编译

    
      rainx@rainx
    
    
      -
    
    
      laptop
    
    
      :~/
    
    
      land
    
    
      /
    
    
      nginx
    
    
      -
    
    
      0.7
    
    
      .
    
    
      61
    
    
      $ 
    
    
      ./
    
    
      configure 
    
    
      --
    
    
      prefix
    
    
      =
    
    
      /home/
    
    
      rainx
    
    
      /
    
    
      land
    
    
      /
    
    
      test 
    
    
      --
    
    
      with
    
    
      -
    
    
      debug
    
  

然后修改nginx.conf

    
      worker_processes  
    
    
      2
    
    
      ;
    
    
       
error_log  logs
    
    
      /
    
    
      error
    
    
      .
    
    
      log  debug
    
    
      ;
    
  

打开debug信息的支持,并使用2个worker进程,通过查看 log 信息来了解 nginx 运行的情况

基于上面的配置信息,结合一个简单的http访问操作,我这里记录了一个  log日志的例子

ngx_init_cycle

其中一个比较重要的函数调用是, ngx_init_cycle, 这个是使用kscope输出的他的调用关系,他被main, ngx_master_process_cycle,ngx_single_process_cycle 调用, 其中后两者是在reconfigure的时候被调用的

他主要做了如下几件事情:

    
      初始化
    
    
      cycle
    
    
      是基于旧有的
    
    
      cycle
    
    
      进行的,比如这里的
    
    
       init_cycle
    
    
      ,会继承
    
    
      old cycle
    
    
      的很多属性,
    
    
    
    
      比如
    
    
      log
    
    
      等,
    
    
    
    
      但是同时会对很多资源重新分配,比如
    
    
      pool
    
    
      ,
    
    
       shared mem
    
    
      ,
    
    
       file handler
    
    
      ,
    
    
       listening socket 
    
    
      等,同时清除旧有的
    
    
      cycle
    
    
      的资源
    
    
    
  

另外,ngx_master/single_process_cycle 里面会对init_process进行调用, 并且循环调用 ngx_process_events_and_timers , 其中里面会调用ngx_process_events(cycle, timer, flags); 对事件循环进行polliing 时间一般默认为 500 ms

了解nginx的http core module 的结构和运行机制

HTTP相关的Module都在 src/http 目录和其子目录下, 其中 src/http 下的文件为http模块的核心文件, src/http/modules 下的文件为http模块的扩展模块。

其中:

ngx_http.[c|h]

ngx_http.c 中,注册了 http 这个指令的处理模块,对应ngx_http_block函数

    
      static
    
    
       ngx_command_t  ngx_http_commands
    
    
      []
    
    
    
    
      =
    
    
    
    
      {
    
    
      

    
    
    
      {
    
    
       ngx_string
    
    
      (
    
    
      "http"
    
    
      ),
    
    
      
      NGX_MAIN_CONF
    
    
      |
    
    
      NGX_CONF_BLOCK
    
    
      |
    
    
      NGX_CONF_NOARGS
    
    
      ,
    
    
      
      ngx_http_block
    
    
      ,
    
    
      
      
    
    
      0
    
    
      ,
    
    
      
      
    
    
      0
    
    
      ,
    
    
      
      NULL 
    
    
      },
    
    
      

      ngx_null_command

    
    
      };
    
  

这个函数里面会进行一些conf资源分配/Merge,配置文件解析等工作。 这里面有个一比较重要的工作是注册了nginx http 的 phase handler

    
          
    
    
      if
    
    
    
    
      (
    
    
      ngx_http_init_phase_handlers
    
    
      (
    
    
      cf
    
    
      ,
    
    
       cmcf
    
    
      )
    
    
    
    
      !=
    
    
       NGX_OK
    
    
      )
    
    
    
    
      {
    
    
      
        
    
    
      return
    
    
       NGX_CONF_ERROR
    
    
      ;
    
    
      
    
    
    
      }
    
  

phase handler的类型在 ngx_http_core_module 这里定义:

    
      typedef
    
    
    
    
      enum
    
    
    
    
      {
    
    
      
    NGX_HTTP_POST_READ_PHASE 
    
    
      =
    
    
    
    
      0
    
    
      ,
    
    
      

    NGX_HTTP_SERVER_REWRITE_PHASE
    
    
      ,
    
    
      

    NGX_HTTP_FIND_CONFIG_PHASE
    
    
      ,
    
    
      
    NGX_HTTP_REWRITE_PHASE
    
    
      ,
    
    
      
    NGX_HTTP_POST_REWRITE_PHASE
    
    
      ,
    
    
      

    NGX_HTTP_PREACCESS_PHASE
    
    
      ,
    
    
      

    NGX_HTTP_ACCESS_PHASE
    
    
      ,
    
    
      
    NGX_HTTP_POST_ACCESS_PHASE
    
    
      ,
    
    
      

    NGX_HTTP_TRY_FILES_PHASE
    
    
      ,
    
    
      
    NGX_HTTP_CONTENT_PHASE
    
    
      ,
    
    
      

    NGX_HTTP_LOG_PHASE

    
    
      }
    
    
       ngx_http_phases
    
    
      ;
    
  

每一个phase的handlers 都是一个数组,里面可以包含多个元素,通过 ngx_array_push 添加新的handler

其中每个phase的处理大都包含了对ngx_request_t 的 write 或者 read event的改写,其中

在 ngx_http_core_content_phase 里面, 有对location handler的调用, 其中的 r->content_handler 就是运行时刻从location handler中注册的,

    
          
    
    
      if
    
    
    
    
      (
    
    
      r
    
    
      ->
    
    
      content_handler
    
    
      )
    
    
    
    
      {
    
    
      
        r
    
    
      ->
    
    
      write_event_handler 
    
    
      =
    
    
       ngx_http_request_empty_handler
    
    
      ;
    
    
      
        ngx_http_finalize_request
    
    
      (
    
    
      r
    
    
      ,
    
    
       r
    
    
      ->
    
    
      content_handler
    
    
      (
    
    
      r
    
    
      ));
    
    
    
    
      /*实际的请求发送处理*/
    
    
      
        
    
    
      return
    
    
       NGX_OK
    
    
      ;
    
    
      
    
    
    
      }
    
  

其中, 在各个phase的结束阶段,一般都是调用

    
          r
    
    
      ->
    
    
      phase_handler
    
    
      ++;
    
    
      
    
    
    
      return
    
    
       NGX_AGAIN
    
    
      ;
    
  

移动request 中 phase_handler的指针,并且示意主程序继续进行。

这里,无论是phase handler,还是 location handler,我们都是可以在程序里进行注册的。

另外, ngx_http_block 里面调用了 ngx_http_optimize_servers ,这个函数对listening和connection相关的变量进行了初始化和调优,并最终在 ngx_http_add_listening (被ngx_http_add_listening调用) 中注册了listening 的 handler 为 ngx_http_init_connection

    
          ls
    
    
      ->
    
    
      handler 
    
    
      =
    
    
       ngx_http_init_connection
    
    
      ;
    
  

ngx_http_init_connection 在 ngx_http_request.c中定义,后续会进行详细的介绍

ngx_http_request.[c|h]

这里面,ngx_http_init_connection 注册了connection事件的读操作的回叫函数, 并将写操作设置为空函数

    
          rev 
    
    
      =
    
    
       c
    
    
      ->
    
    
      read
    
    
      ;
    
    
      
    rev
    
    
      ->
    
    
      handler 
    
    
      =
    
    
       ngx_http_init_request
    
    
      ;
    
    
      
    c
    
    
      ->
    
    
      write
    
    
      ->
    
    
      handler 
    
    
      =
    
    
       ngx_http_empty_handler
    
    
      ;
    
  

当新的连接进入的时候,就执行到 ngx_http_init_request, 开始对后面的流程进行处理,主要是将rev的handler 设置为ngx_http_process_request_line , 然后ngx_http_process_request_line 会先后有调度到 ngx_http_process_request_headers 和 ngx_http_process_request 函数对读取过来的event进行处理,其中, ngx_http_process_request_headers 里面会对http的请求头进行解析,ngx_http_process_request 设置event handler 到ngx_http_request_handler ,ngx_http_request_handler 中会根据事件可能是读取还是写入的操作分别调用 request 的 read_event_handler 和 write_event_handler ,所以后续程序对 request 的 read/write event_handler 调整 本质上类似对 rev 和 wev的handler的调整,只是回叫函数的参数变更为了 ngx_request_t 而不是之前的ngx_event_t

    
          c
    
    
      ->
    
    
      read
    
    
      ->
    
    
      handler 
    
    
      =
    
    
       ngx_http_request_handler
    
    
      ;
    
    
      
    c
    
    
      ->
    
    
      write
    
    
      ->
    
    
      handler 
    
    
      =
    
    
       ngx_http_request_handler
    
    
      ;
    
    
      
    r
    
    
      ->
    
    
      read_event_handler 
    
    
      =
    
    
       ngx_http_block_reading
    
    
      ;
    
  

根据上面代码可以看出, 模块开始使用 ngx_http_block_reading 这个handler对后续的读请求进行处理

在注册完事件后, ngx_http_process_request 会分别调用下面的两个函数

    
          ngx_http_handler
    
    
      (
    
    
      r
    
    
      );
    
    
      
    ngx_http_run_posted_requests
    
    
      (
    
    
      c
    
    
      );
    
  

其中, ngx_http_handler 在ngx_http_core_module中定义,处理程序的主请求, ngx_http_run_posted_requests 在ngx_http_request.c 里定义,处理所有提交的子请求数据的输出。

ngx_http_core_module.[c|h]

对于 ngx_http_core_module 是http 模块中比较重要的模块, 他本身是一个 NGX_HTTP_MODULE (不同于ngx_http_module, ngx_http_module本质上是一个 NGX_CORE_MODULE

这里面对http block下面的一些指令进行了处理, 比如 server, location 等, 同时, 上面提到的 ngx_http_handler 也在这里面

ngx_http_handler 所作的最核心的工作就是在最后调用 并将 write event 设置为 ngx_http_core_run_phases, 开始依次处理各个阶段的 handler

当handler处理完成后,http的处理流程也就基本上完成了..

    
          
    
    
      while
    
    
    
    
      (
    
    
      ph
    
    
      [
    
    
      r
    
    
      ->
    
    
      phase_handler
    
    
      ].
    
    
      checker
    
    
      )
    
    
    
    
      {
    
    
      

        rc 
    
    
      =
    
    
       ph
    
    
      [
    
    
      r
    
    
      ->
    
    
      phase_handler
    
    
      ].
    
    
      checker
    
    
      (
    
    
      r
    
    
      ,
    
    
    
    
      &
    
    
      ph
    
    
      [
    
    
      r
    
    
      ->
    
    
      phase_handler
    
    
      ]);
    
    
      

        
    
    
      if
    
    
    
    
      (
    
    
      rc 
    
    
      ==
    
    
       NGX_OK
    
    
      )
    
    
    
    
      {
    
    
      
            
    
    
      return
    
    
      ;
    
    
      
        
    
    
      }
    
    
      
    
    
    
      }
    
  

run_phases 的过程实际上非常简单, 一次的运行每一个handler, 当任意一个handler返回ok或者所有handler执行完成后,整个流程结束。

这里需要注意的是, ph的下标变化是根据 r->phase_handler 变量决定的, 所以在每个handler内部,如果想要让主程序继续处理下一个 handler,需要手动的 r->phase_handler++ ,将phase handler数组的下标转移到下一个成员。


Ningx代码研究(四)


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

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

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

【本文对您有帮助就好】

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

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