博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

nginx 配置结构的创建

Posted on 2016-03-03 16:15  bw_0927  阅读(257)  评论(0)    收藏  举报

http://blog.chinaunix.net/uid-27767798-id-3757684.html

http://blog.csdn.net/brainkick/article/details/6842216

http://blog.sunheqiubai.com/?cat=5&paged=2

http://blog.csdn.net/chosen0ne/article/details/7730292

 

在nginx中每个块都会对应一个相应类型core module,比如整个配置文件的main块对应的就是ngx_core_module,events块对应的是ngx_event_core_module,而http块对应就是ngx_http_core_module。这些具体类型的core module主要是处理相应块内的指令,并保存一些重要的配置信息。

 

nginx配置文件解析时,会首先解析core module,然后由core module再去解析相应类型的module,比如由ngx_http_module(这是一个core module)负责解析所有的http module,而由ngx_events_module(也是一个core module)解析所有的event module。如果把配置文件看成一棵树:
               Main
              /      \

     Events         Http

                     /          \

               Server          Server

              /        \                   \

       Location     Location      Location

       

这棵树中,每个节点对应一个配置块,配置文件的解析就是对这棵树的深度优先遍历,并对每个节点调用ngx_conf_parse函数。其中的Http节点对应的就是ngx_http_module模块,是由它驱动后面的server块和location块的解析

 

 

 

 

 

//ngx_module_s只是一个通用的模块数据结构,对于具体的模块类型是它的ctx字段
struct ngx_module_s {
    ngx_uint_t            ctx_index;    //同一类型的模块索引
    ngx_uint_t            index;

    ngx_uint_t            spare0;
    ngx_uint_t            spare1;
    ngx_uint_t            spare2;
    ngx_uint_t            spare3;

    ngx_uint_t            version;

    void                 *ctx;
    ngx_command_t        *commands;
    ngx_uint_t            type;    //模块的类型,五大类型:NGX_CORE_MODULE, NGX_CONF_MODULE, NGX_HTTP_MODULE, NGX_EVENT_MODULE, NGX_MAIL_MODULE

    ngx_int_t           (*init_master)(ngx_log_t *log);

    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);

    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);
    ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);
    void                (*exit_thread)(ngx_cycle_t *cycle);
    void                (*exit_process)(ngx_cycle_t *cycle);

    void                (*exit_master)(ngx_cycle_t *cycle);

    uintptr_t             spare_hook0;
    uintptr_t             spare_hook1;
    uintptr_t             spare_hook2;
    uintptr_t             spare_hook3;
    uintptr_t             spare_hook4;
    uintptr_t             spare_hook5;
    uintptr_t             spare_hook6;
    uintptr_t             spare_hook7;
};

  

 

获得模块的配置:

ngx_get_conf(cycle->conf_ctx, ngx_events_module);

 

 

是核心模块且其字段create_conf非空的模块配置的创建在ngx_init_cycle()中:

    for (i = 0; ngx_modules[i]; i++) {
        if (ngx_modules[i]->type != NGX_CORE_MODULE) {
            continue;
        }

        module = ngx_modules[i]->ctx;

        if (module->create_conf) {
            rv = module->create_conf(cycle);
            if (rv == NULL) {
                ngx_destroy_pool(pool);
                return NULL;
            }
            cycle->conf_ctx[ngx_modules[i]->index] = rv;
        }
    }

  

 

模块的配置结构创建存储都是在配置解析过程中完成的

 NGX_EVENT_MODULE类型模块配置结构的创建在解析配置文件的时候

(gdb) bt
#0 ngx_event_core_create_conf (cycle=0x6f6780) at src/event/ngx_event.c:1162
#1 0x000000000042b17b in ngx_events_block (cf=0x7fffffffe290, cmd=0x6d4b00, conf=0x6f7648) at src/event/ngx_event.c:920
#2 0x000000000041de01 in ngx_conf_handler (cf=0x7fffffffe290, last=1) at src/core/ngx_conf_file.c:391
#3 0x000000000041d9ad in ngx_conf_parse (cf=0x7fffffffe290, filename=0x6f6900) at src/core/ngx_conf_file.c:247
#4 0x000000000041a560 in ngx_init_cycle (old_cycle=0x7fffffffe3d0) at src/core/ngx_cycle.c:264
#5 0x0000000000403324 in main (argc=1, argv=0x7fffffffe6b8) at src/core/nginx.c:333
(gdb)

 

不过, 在ngx_events_module中实现的核心模块却没有实现此函数, ngx_event_init_conf函数也只是简单进行正确性判断.

这是因为ngx_events_module模块并不会解析配置项的参数, 只是在出现events配置项后会调用各事件模块去解析events{...}块内的配置项, 所以也就不需要什么存储结构体了.

 

 

 

  1. 配置解析的时机是在 fork 调用之前,换句话说所有因为配置解析而产生的内存(包括自定义模块的内存)都是在 fork 之前分配,但是由于 linux 的写时拷贝机制,所以并不会在物理内存中存在多份拷贝;

 

=========================

ngx_init_cycle()中的几件事件:

父进程中

  1. 核心模块的配置结构的显示创建   module->create_conf(cycle)
  2. 非核心模块的配置结构的创建和初始化   ngx_conf_parse()
  3. 核心模块的配置结构的初始化  module->init_conf()
  4. 所有模块的模块初始化   ngx_modules[i]->init_module()

子进程中

  所有模块的进程初始化:  ngx_modules[i]->init_process(cycle)

  见如下调用栈

 

(gdb) bt
#0 ngx_event_process_init (cycle=0x6f6780) at src/event/ngx_event.c:585
#1 0x00000000004379f6 in ngx_worker_process_init (cycle=0x6f6780, worker=0) at src/os/unix/ngx_process_cycle.c:981
#2 0x0000000000437126 in ngx_worker_process_cycle (cycle=0x6f6780, data=0x0) at src/os/unix/ngx_process_cycle.c:746
#3 0x0000000000433ae6 in ngx_spawn_process (cycle=0x6f6780, proc=0x4370f0 <ngx_worker_process_cycle>, data=0x0,
name=0x4b89cb "worker process", respawn=-3) at src/os/unix/ngx_process.c:198
#4 0x0000000000436083 in ngx_start_worker_processes (cycle=0x6f6780, n=3, type=-3) at src/os/unix/ngx_process_cycle.c:368
#5 0x00000000004356c1 in ngx_master_process_cycle (cycle=0x6f6780) at src/os/unix/ngx_process_cycle.c:140
#6 0x0000000000403573 in main (argc=1, argv=0x7fffffffe6b8) at src/core/nginx.c:407

 

ngx_event_process_init ()中module->actions.init(cycle, ngx_timer_resolution),即对ngx_epoll_init()的调用

 

 

 

 

 

 

 

 

 

 

Nginx启动的时候会先进行core类型模块的处理。在Nginx的每一部分都会有一个core类型的模块与之对应,在解析配置文件的时候,这些core类型的模块便是他们所代表部分的入口

例如event部分,ngx_events_module模块就是一个NGX_CORE_MODULE的模块,因而我们可以看到event部分的初始化其实是从ngx_events_module模块的命令events的set回调函数开始的。

 

在每一部分都有一个比较重要的核心模块,例如event部分有NGX_EVENT_MODULE类型的ngx_event_core_module模块,其虽然只是一个event类型的模块,但是其却处理了event部分的大多数命令,

而且它的配置结构也会保存很多十分重要的信息,例如ngx_event_core_module的配置结构ngx_event_conf_t就保存了event是否使用互斥信号,具体使用哪一个时间模块的等信息。

 

其实要分析nginx不同部分就应该从这两种模块开始。

 

分析http部分吧,先找到core类型的模块,它是ngx_http_module模块

 

我们知道每种类型的模块的配置结构并不是保存在模块内部的,我们可以看到全局cycle变量有一个域是ctx,它用来保存“所有”模块的配置结构上下文,这里用引号是有道理的。其实ctx只是保存了每一部分core类型的模块的配置结构

然后再用core类型模块的配置结构来保存其所在部分的其余具体模块的配置结构,然后其余具体模块想要获取其的配置,就得先找到代表它的core类型的模块,进而才能找到其的配置结构。也就是说模块的配置结构的保存其实是按照层次来进行的