【Nginx】核心模块ngx_events_module

来源:互联网 发布:淘宝地区编码 编辑:程序博客网 时间:2024/05/23 01:17
核心模块ngx_events_module是一个专门用于管理事件模块的模块。它的实现很简单,下面是该模块的定义:
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_events_commands结构体数组定义如下:
// 定义了如何处理感兴趣的配置项static ngx_command_t  ngx_events_commands[] = {    {        ngx_string("events"), /* 只对events块配置项感兴趣 */        NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,        ngx_events_block,     /* 解析配置项的函数 */        0,        0,        NULL    },    ngx_null_command}; 


可以看到,核心模块ngx_events_module只对配置文件中的“events”块配置项感兴趣,并用ngx_events_block方法进行解析。ngx_events_block在后面讲解。

通用接口ngx_events_module_ctx定义如下:
static ngx_core_module_t  ngx_events_module_ctx = {    ngx_string("events"),    NULL,                  /* create_conf */    ngx_event_init_conf    /* init_conf */}; 


ngx_event_init_conf函数内貌似没有做什么特别的工作,所以我们可以忽略它,相当于该接口只是定义了该模块的名字而已。这是因为ngx_events_module并不解析配置项参数,只是在events块配置项出现后调用各个事件模块去解析events内的配置项,所以它自己并不需要实现create_conf方法和init_conf方法。

如何管理事件模块配置项
事件模块的通用接口是ngx_event_module_t,定义如下:
typedef struct {    ngx_str_t              *name;   // 事件模块名字    // 解析配置项之前调用,创建存储配置项参数的结构体    void                 *(*create_conf)(ngx_cycle_t *cycle);    // 解析完配置项后的回调函数    char                 *(*init_conf)(ngx_cycle_t *cycle, void *conf);    // 每个事件模块需要实现的10个抽象方法    ngx_event_actions_t     actions;} ngx_event_module_t;   // 事件模块通用接口


每个事件模块使用init_conf成员函数创建存储配置项的结构体并返回指向这个结构体的指针。这个指针放在了ngx_events_module核心模块创建的指针数组中,如下图所示:


这样,每一个进程的核心结构体ngx_cycle_t就能够和所有模块的存储配置项的结构体相关联了。那么每个事件模块调用create_conf方法所返回的指针又是怎样放进核心模块的数组中的呢?还是上面提到的ngx_events_block方法,下面就来讲解ngx_events_block,此函数的流程图如下:


该方法的代码如下,已经被我简化了,注释中的序号对应上面的每一步:
static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf){    char                 *rv;    void               ***ctx;    ngx_uint_t            i;    ngx_conf_t            pcf;    ngx_event_module_t   *m;    ngx_event_max_module = 0;    for (i = 0; ngx_modules[i]; i++)    {        if (ngx_modules[i]->type != NGX_EVENT_MODULE)            continue;        /* 1.初始化所有事件模块的ctx_index成员         * 该成员表明了该模块在相同类型模块中的顺序,这会决定以后加载各事件模块的顺序         */        ngx_modules[i]->ctx_index = ngx_event_max_module++;    }    /* 分配一个存放指针的空间 */    ctx = ngx_pcalloc(cf->pool, sizeof(void *));    /* 2.ngx_event_max_module等于事件模块个数 */    *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));    *(void **) conf = ctx;  /* conf指向存储参数的结构体 */    for (i = 0; ngx_modules[i]; i++)    {        if (ngx_modules[i]->type != NGX_EVENT_MODULE)            continue;        m = ngx_modules[i]->ctx;    /* 得到事件模块的通用接口 */        if (m->create_conf)            /* 3.调用所有事件模块的通用接口ngx_event_module_t中的create_conf方法 */            (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);    }    pcf = *cf;    cf->ctx = ctx;    cf->module_type = NGX_EVENT_MODULE;    cf->cmd_type = NGX_EVENT_CONF;    /* 4.针对所有事件模块调用各自的解析配置文件的方法     * 当发现相应配置项后,就调用模块中ngx_command_t数组中的方法     */    rv = ngx_conf_parse(cf, NULL);  /* cf中保存有读到的配置项参数 */    *cf = pcf;    for (i = 0; ngx_modules[i]; i++)    {        if (ngx_modules[i]->type != NGX_EVENT_MODULE)            continue;        m = ngx_modules[i]->ctx;        if (m->init_conf)            /* 5.解析完配置项后,调用每个模块的init_conf方法对配置参数进行整合 */            rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i]->ctx_index]);    }    return NGX_CONF_OK;} 


以上代码用ngx_pcalloc函数分配了两块内存,第一个ngx_pcalloc创建一个能够存放指针的空间,相当于图9-2上面那个数组中的第四个单元;而第二个ngx_pcalloc则创建了一个指针数组,存放指针的数量等于事件模块的数量,对应图9-2下面的那个数组。此函数执行完毕时,所有事件模块都在核心模块ngx_events_module的管理下成功读取配置项。

以上就是管理事件的核心模块ngx_events_module。事件驱动机制更多的工作是在ngx_event_core_module模块中完成,下次再写。

参考:
《深入理解Nginx》 P300-P305.
0 0
原创粉丝点击