核心模块ngx_events_module是一个专门用于管理事件模块的模块。

它的实现非常easy。以下是该模块的定义:

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.

最新文章

  1. CentOS 6.5 安全加固及性能优化 (转)
  2. Android编译过程中的碎碎念
  3. ibatis实现Iterate的使用
  4. Traffic Lights
  5. 使用 TC 对LInux中vpn 上传下载进行限速(转)
  6. 如何在linux系统下对文件夹名有空格的文件夹进行操作
  7. jquery实现替代iframe的功能
  8. VS2015使用scanf报错解决方案
  9. HttpResponseRedirect VS HttpResponse
  10. php薪资
  11. C# Web.config 配置handlers 和 httpHandlers
  12. RDC去省赛玩前の日常训练 Chapter 1
  13. 【导航】FPGA相关
  14. eclipse查看一个方法被谁引用(调用)的快捷键四种方式
  15. 【bzoj3174】[Tjoi2013]拯救小矮人
  16. AMR文件结构
  17. .NET Core容器化之多容器应用部署-使用Docker-Compose
  18. 【初探】java性能火焰图的生成
  19. EditText把回车键变成搜索
  20. MFC多语言程序版本,在不同的windows系统上的使用 FP_SetThreadUILanguage

热门文章

  1. [bzoj3218]a + b Problem 网络流+主席树优化建图
  2. STL模板整理 map
  3. Codeforces 651 B. Beautiful Paintings
  4. scrapy中Selector的使用
  5. (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest
  6. 数据库的语言——SQL
  7. 【最短路】【Heap-dijkstra】Gym - 101147B - Street
  8. 【动态规划】【记忆化搜索】CODEVS 1011 数的计算 2001年NOIP全国联赛普及组
  9. 高性能mysql读后感
  10. 【转载】Mini2440启动配置文件说明