1. ngx_events_module核心模块的功能介绍

ngx_events_module 模式是一个核心模块,它的功能如下:

  • 定义新的事件类型
  • 定义每个事件模块都需要实现的ngx_event_module_t接口
  • 管理这些事件模块生成的配置项结构体,并解析事件类配置项,同时,在解析配置项时会调用其在ngx_command_t数组中定义的配置项结构体.

2. ngx_events_module的框架实现

2.1 ngx_events_module的配置项

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
};

ngx_events_module 模块只对一个块配置项感兴趣,也就是 nginx.conf 中必须有的 events{} 配置项。

2.2 核心模块的通用接口

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

这里,ngx_events_module_ctx 只是实现了init_conf方法,而没有实现create_conf方法,这是因为ngx_events_module模块

并不会解析配置项的参数,只是在出现 "events" 配置项后会调用各事件模块去解析 events{} 块内的配置项。init_conf方

法仅是检测是否能获取到ngx_events_module模块的保存在cycle->conf_ctx数组中的配置项结构体,该结构体保存着所有事件

模块的配置项。

static char *ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
{
if (ngx_get_conf(cycle->conf_ctx, ngx_events_module) == NULL) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
"no \"events\" section in configuration");
return NGX_CONF_ERROR;
} return NGX_CONF_OK;
}

2.3 模块的定义

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_module模块除了对 events 配置项的解析外,没有做其他任何事情。

3. ngx_events_module的配置项管理

3.1 如何管理所有事件模块的配置项

每一个事件模块都必须实现ngx_event_module_t接口,这个接口中允许每个事件模块建立自己的配置项结构体,用于存储自己

感兴趣的配置项在nginx.conf中对应的参数。ngx_event_module_t 中的 create_conf 方法就是用于创建这个结构体的方法,

事件模块只需要在这个方法中分配内存即可。

每一个事件模块产生的配置结构体指针都会被放到 ngx_events_module 模块创建的指针数组中。而 ngx_cycle_t 核心结构体

中的 conf_ctx 成员,它指向一个指针数组,这个指针数组中就依次存放着所有的 Nginx 模块关于配置项方面的指针。因

此,核心模块 ngx_events_module 管理所有事件模块的总配置项结构体就按 ngx_events_module 模块在全部 Nginx 模块中

的排序号放入到 ngx_cycle_t 核心结构体的成员 conf_ctx 指针数组中的对应下标处。

ngx_cycle_t 结构体中 conf_ctx 的结构示意图

3.2 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; /* 检测配置项结构体是否已经存在 */
if (*(void **) conf) {
return "is duplicate";
} /* count the number of the event modules and set up their indices */ /* 计算出编译进 Nginx 的所有事件模块的总个数 */
ngx_event_max_module = ngx_count_modules(cf->cycle, NGX_EVENT_MODULE); /* 创建该核心事件存储所有事件模块的总配置项结构体指针 */
ctx = ngx_pcalloc(cf->pool, sizeof(void *));
if (ctx == NULL) {
return NGX_CONF_ERROR;
} /* 为每个事件模块都分配一个空间用于放置指向该事件模块的配置项结构体指针 */
*ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));
if (*ctx == NULL) {
return NGX_CONF_ERROR;
} /* conf 其实就是核心模块 ngx_events_module 在 ngx_cycle_t 核心结构体的成员 conf_ctx 指针数组
* 相应位置的指针 */
*(void **) conf = ctx; /* 调用所有事件模块的 create_conf 方法 */
for (i = 0; cf->cycle->modules[i]; i++) {
if (cf->cycle->modules[i]->type != NGX_EVENT_MODULE) {
continue;
} m = cf->cycle->modules[i]->ctx; if (m->create_conf) {
(*ctx)[cf->cycle->modules[i]->ctx_index] =
m->create_conf(cf->cycle);
if ((*ctx)[cf->cycle->modules[i]->ctx_index] == NULL) {
return NGX_CONF_ERROR;
}
}
} pcf = *cf;
cf->ctx = ctx;
cf->module_type = NGX_EVENT_MODULE;
cf->cmd_type = NGX_EVENT_CONF; /* 开始解析 events{} 配置块 */
rv = ngx_conf_parse(cf, NULL); *cf = pcf; if (rv != NGX_CONF_OK) {
return rv;
} /* 解析配置项完成后,调用各事件模块的 init_conf 方法 */
for (i = 0; cf->cycle->modules[i]; i++) {
if (cf->cycle->modules[i]->type != NGX_EVENT_MODULE) {
continue;
} m = cf->cycle->modules[i]->ctx; if (m->init_conf) {
rv = m->init_conf(cf->cycle,
(*ctx)[cf->cycle->modules[i]->ctx_index]);
if (rv != NGX_CONF_OK) {
return rv;
}
}
} return NGX_CONF_OK;
}

最新文章

  1. C#多线程之旅(3)——线程池
  2. 省市县 三级 四级联动Javascript JQ 插件PCASClass.js
  3. 关于PIL库的一些概念
  4. 【 java版坦克大战--事件处理】 坦克动起来了
  5. C++类的数组元素查找最大值问题
  6. jQuery整理笔记2----jQuery选择整理
  7. 第一百零五节,JavaScript正则表达式
  8. .net core nlog记录日志
  9. mysql中游标的使用案例详解(学习笔记)
  10. 快看我解决了一个Nginx的小问题
  11. .NET 二维码生成(ThoughtWorks.QRCode)【转发jiangys】
  12. Week 1 # A A + B Problem II
  13. 使用PowerDesigner对NAME和COMMENT互相转换
  14. JSP1.x 自定义标签
  15. window.history.back(-1);与window.go(-1);的区别
  16. layui 弹窗的iframe 父子界面相互传值
  17. 兼容IE浏览器样式的html上传文件控件
  18. PHP工厂模式demo
  19. JMeter学习(三十四)使用jmeter来发送json/gzip格式数据(转载)
  20. 了解java内存模型,看这里就够了

热门文章

  1. python之项目依赖管理
  2. ActiveMQ入门操作示例
  3. 附件上传vue组件封装(一)
  4. 语义分割之RefineNet
  5. linux获取某一个网卡的ipv4地址
  6. hadoop/hbase/hive单机扩增slave
  7. 阿里云端安装mysql
  8. SpringData JPA 在解析实体类字段时驼峰自动添加下划线问题
  9. JS 获取和返填单选按钮Value值
  10. elementUI + vue 输入框只能输入正整数 不能输入字母 e 以及+ - 号