nginx中void****ctx如何初始化

nginx的一切都是通过ngx_cycle_s来展开的,按看一下其第一个参数:

struct ngx_cycle_s {
    void                  ****conf_ctx;
    ngx_pool_t               *pool;
    ...
    }

注意conf_ctx有四个指针,就是数组的数组,那么它是怎么初始化的呢?
我们在这里先列出几个核心模块:

//第一个核心模块为ngx_core_module,在nginx.c中
static ngx_command_t  ngx_core_commands[] = {

    { ngx_string("daemon"),
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      0,
      offsetof(ngx_core_conf_t, daemon),
      NULL },

    { ngx_string("master_process"),
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      0,
      offsetof(ngx_core_conf_t, master),
      NULL },
      ....
      }
static ngx_core_module_t  ngx_core_module_ctx = {
    ngx_string("core"),
    ngx_core_module_create_conf,
    ngx_core_module_init_conf
};


ngx_module_t  ngx_core_module = {
    NGX_MODULE_V1,
    &ngx_core_module_ctx,                  /* module context */
    ngx_core_commands,                     /* module directives */
    NGX_CORE_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    NULL,                                  /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,                                  /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};

//第二个模块是conf模块,只有一个,比较特殊
static ngx_command_t  ngx_conf_commands[] = {

    { ngx_string("include"),
      NGX_ANY_CONF|NGX_CONF_TAKE1,
      ngx_conf_include,
      0,
      0,
      NULL },

      ngx_null_command
};


ngx_module_t  ngx_conf_module = {
    NGX_MODULE_V1,
    NULL,                                  /* module context */
    ngx_conf_commands,                     /* module directives */
    NGX_CONF_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    NULL,                                  /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    ngx_conf_flush_files,                  /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};


/* The eight fixed arguments */

static ngx_uint_t argument_number[] = {
    NGX_CONF_NOARGS,
    NGX_CONF_TAKE1,
    NGX_CONF_TAKE2,
    NGX_CONF_TAKE3,
    NGX_CONF_TAKE4,
    NGX_CONF_TAKE5,
    NGX_CONF_TAKE6,
    NGX_CONF_TAKE7
};

//第三个核心模块为ngx_events_module,在ngx_event.c中
static ngx_command_t  ngx_events_commands[] = {

    { ngx_string("events"),
      NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_events_block,
      0,
      0,
      NULL },

      ngx_null_command
};


static ngx_core_module_t  ngx_events_module_ctx = {
    ngx_string("events"),
    NULL,
    ngx_event_init_conf
};


ngx_module_t  ngx_events_module = {
    NGX_MODULE_V1,
    &ngx_events_module_ctx,                /* module context */
    ngx_events_commands,                   /* module directives */
    NGX_CORE_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    NULL,                                  /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,                                  /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};
//第四个核心模块是ngx_http_module,在ngx_http.c中
ngx_uint_t   ngx_http_max_module;


ngx_http_output_header_filter_pt  ngx_http_top_header_filter;
ngx_http_output_body_filter_pt    ngx_http_top_body_filter;
ngx_http_request_body_filter_pt   ngx_http_top_request_body_filter;
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
};


static ngx_core_module_t  ngx_http_module_ctx = {
    ngx_string("http"),
    NULL,
    NULL
};


ngx_module_t  ngx_http_module = {
    NGX_MODULE_V1,
    &ngx_http_module_ctx,                  /* module context */
    ngx_http_commands,                     /* module directives */
    NGX_CORE_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    NULL,                                  /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,                                  /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};
//第五个核心模块是ngx_rtmp_module
ngx_uint_t  ngx_rtmp_max_module;
static ngx_command_t  ngx_rtmp_commands[] = {

    { ngx_string("rtmp"),
      NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_rtmp_block,
      0,
      0,
      NULL },

      ngx_null_command
};


static ngx_core_module_t  ngx_rtmp_module_ctx = {
    ngx_string("rtmp"),
    NULL,
    NULL
};


ngx_module_t  ngx_rtmp_module = {
    NGX_MODULE_V1,
    &ngx_rtmp_module_ctx,                  /* module context */
    ngx_rtmp_commands,                     /* module directives */
    NGX_CORE_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    ngx_rtmp_init_process,                 /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,                                  /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};

以上就是我们本次关心的几个核心模块

下面再ngx_cycle.c的main中:

 main-->ngx_init_cycle(){
 ...
 //在这里分配空间,ngx_max_module就是ngx_module_t *ngx_modules[] + 128,
 //ngx_modules[]有config生成:
 //ngx_module_t *ngx_modules[] = {
//    &ngx_core_module,
//    &ngx_errlog_module,
//    &ngx_conf_module,
//    &ngx_rtmp_module,
//    &ngx_rtmp_core_module,
//    ‘’‘’
//    &ngx_openssl_module,
//    &ngx_regex_module, //通配符
//    &ngx_events_module,
//    &ngx_event_core_module,
//    &ngx_epoll_module,
//    &ngx_http_module,
//    &ngx_http_core_module,
//    ‘’‘’‘
//   
// }
 
   cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
    if (cycle->conf_ctx == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

...

//在这里调用核心模块的create_conf函数,通过上面可以知道,只有ngx_core_module才有create_conf
//其余核心模块没有,那么其余模块是在什么时候create_conf呢?
//其实其余的都是在 ngx_xxxx_block,中开始创建的
    for (i = 0; cycle->modules[i]; i++) {
        if (cycle->modules[i]->type != NGX_CORE_MODULE) {
            continue;
        }

        module = cycle->modules[i]->ctx;

        if (module->create_conf) {
            rv = module->create_conf(cycle);
            if (rv == NULL) {
                ngx_destroy_pool(pool);
                return NULL;
            }
            cycle->conf_ctx[cycle->modules[i]->index] = rv;
        }
    }
    ’‘’‘’‘
//在这个for循环中进行NGX_CORE_MODULE初始化
for (i = 0; cycle->modules[i]; i++) {
        if (cycle->modules[i]->type != NGX_CORE_MODULE) {
            continue;
        }

        module = cycle->modules[i]->ctx;

        if (module->init_conf) {
            if (module->init_conf(cycle,
                                  cycle->conf_ctx[cycle->modules[i]->index])
                == NGX_CONF_ERROR)
            {
                environ = senv;
                ngx_destroy_cycle_pools(&conf);
                return NULL;
            }
        }
    }

’‘’‘
//注意这个conf是做什么用的?
//struct ngx_conf_s {
//    char                 *name;
//    ngx_array_t          *args;
//
//    ngx_cycle_t          *cycle;
//    ngx_pool_t           *pool;
//    ngx_pool_t           *temp_pool;
//    ngx_conf_file_t      *conf_file;
//    ngx_log_t            *log;
//
//    void                 *ctx;
//    ngx_uint_t            module_type;
//    ngx_uint_t            cmd_type;

//    ngx_conf_handler_pt   handler;
//    void                 *handler_conf;
//};
  ngx_memzero(&conf, sizeof(ngx_conf_t));
    /* STUB: init array ? */
    conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));
    if (conf.args == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

    conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
    if (conf.temp_pool == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }


    conf.ctx = cycle->conf_ctx;
    conf.cycle = cycle;
    conf.pool = pool;
    conf.log = log;
    conf.module_type = NGX_CORE_MODULE;
    conf.cmd_type = NGX_MAIN_CONF;
    
    if (ngx_conf_param(&conf) != NGX_CONF_OK) {
        environ = senv;
        ngx_destroy_cycle_pools(&conf);
        return NULL;
    }
//这里就是开始解析配置文件了,注意传入的conf
//ngx_conf_parse---->
//  for(;;){
//       rc = ngx_conf_read_token(cf);
//       //核心就在这里
//		 rc = ngx_conf_handler(cf, rc);
//}
//ngx_conf_handler核心for循环{}如下:
//遍历所有commands
// name = cf->args->elts;这个name就是解析到的nginx.conf
//关于nginx.conf可以参考:
//for (i = 0; cf->cycle->modules[i]; i++) {
//        cmd = cf->cycle->modules[i]->commands;
//        if (cmd == NULL) {
//            continue;
//        }

//        for ( /* void */ ; cmd->name.len; cmd++) {//简单len比较
//            if (name->len != cmd->name.len) {
//                continue;
//            }

//            if (ngx_strcmp(name->data, cmd->name.data) != 0) {//len相等再对str比较
//                continue;
//            }
//            found = 1;//说明字符串跟command中的相同

//            //如果模块类型不符返回
//            if (cf->cycle->modules[i]->type != NGX_CONF_MODULE
//                && cf->cycle->modules[i]->type != cf->module_type)
//            {
//                continue;
//            }

‘‘’
// cmd就是执行核心模块的command中的set,因为在配置文件中只有核心模块的名字
// http 、rtmp 、events 才出现在配置文件中,更加确切的说,这里执行的是核心模块
// 的		ngx_xxxx_block,继续创建NGX_EVENT_MODULE、
//struct ngx_command_s {
//    ngx_str_t             name;
//    ngx_uint_t            type;
//    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
//    ngx_uint_t            conf;
//    ngx_uint_t            offset;
//    void                 *post;
};
//            rv = cmd->set(cf, cmd, conf);//关键在这里

//            if (rv == NGX_CONF_OK) {
//                return NGX_OK;
//            }

//            if (rv == NGX_CONF_ERROR) {
//                return NGX_ERROR;
//            }

//            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                               "\"%s\" directive %s", name->data, rv);

//            return NGX_ERROR;
//        }
//    }

   if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
        environ = senv;
        ngx_destroy_cycle_pools(&conf);
        return NULL;
    }
}
上一篇:nginx 基础结构


下一篇:kubernetes