9.4.2 管理事件模块

上文说到,配置项结构体指针的保存都是在ngx_events_block方法中进行的。下面再来看一下这个方法执行的流程图,如图9-3所示。

9.4.2 管理事件模块 - 图1

图 9-3 ngx_events_module核心模块如何加载事件模块

下面简要描述一下这5个步骤。

1)首先初始化所有事件模块的ctx_index成员。这里要先回顾一下ngx_module_t模块接口的定义,如下所示。


struct ngx_module_s{

ngx_uint_t ctx_index;

ngx_uint_t index;

……

}


这里的index是所有模块在ngx_modules.c文件的ngx_modules数组中的序号,它与ngx_modules数组中所有模块的顺序是一致的。什么时候初始化这个index呢?启动Nginx后,在调用第8章中介绍过的ngx_init_cycle方法前就会进行,代码如下。


ngx_max_module=0;

for(i=0;ngx_modules[i];i++){

ngx_modules[i]->index=ngx_max_module++;

}


其中,ngx_max_module是Nginx模块的总个数。注意,本书前文曾多次提到过,Nginx各模块在ngx_modules数组中的顺序是很重要的,依靠index成员,每一个模块才可以把自己的位置与其他模块的位置进行比较,并以此决定行为。但是,Nginx同时又允许再次定义子类型,如事件类型、HTTP类型、mail类型,那同一类型的模块间又如何区分顺序呢(依靠index当然可以区分顺序,但index是针对所有模块的,这样效率太差)?这就得依靠ctx_index成员了。ctx_index表明了模块在相同类型模块中的顺序。

因此,ngx_events_block方法的第一步就是初始化所有事件模块的ctx_index成员,这会决定以后加载各事件模块的顺序。其代码非常简单,如下所示。


ngx_event_max_module=0;

for(i=0;ngx_modules[i];i++){

if(ngx_modules[i]->type!=NGX_EVENT_MODULE){

continue;

}

ngx_modules[i]->ctx_index=ngx_event_max_module++;

}


其中,ngx_event_max_module是编译进Nginx的所有事件模块的总个数。

2)分配9.4.1节中介绍的指针数组,不再详述。

3)依次调用所有事件模块通用接口ngx_event_module_t中的create_conf方法,当然,产生的结构体的指针保存在上面的指针数组中。

4)针对所有事件类型的模块解析配置项。这时,每个事件模块定义的ngx_command_t决定了配置项的解析方法,如果在nginx.conf中发现相应的配置项,就会回调各事件模块定义的方法。

5)解析完配置项后,依次调用所有事件模块通用接口ngx_event_module_t中的init_conf方法,实现了这个方法的事件模块可以在此做一些配置参数的整合工作。

以上就是ngx_events_module模块的核心工作流程。对于事件驱动机制,更多的工作是在ngx_event_core_module模块中进行的,下面继续看一下这个模块做了些什么。