ngx_events_block

在 src\event\ngx_event.c

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 */

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

    *(void **) conf = ctx;

    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;

    rv = ngx_conf_parse(cf, NULL);

    *cf = pcf;

    if (rv != NGX_CONF_OK) {
        return rv;
    }

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

ngx_events_block 函数是 Nginx 在解析配置文件中 events{} 块时的核心处理函数


    if (*(void **) conf) {
        return "is duplicate";
    }

conf 解引用 如果不是 NULL,那么意味着 已经解析过 events 指令,此时再次解析属于重复配置


此时

(*conf)=(nil)

条件不成立


    /* count the number of the event modules and set up their indices */

    ngx_event_max_module = ngx_count_modules(cf->cycle, NGX_EVENT_MODULE);

统计 Nginx 中事件模块(NGX_EVENT_MODULE)的数量,并为每个模块分配唯一的索引
通过 ngx_count_modules 函数遍历所有模块,统计类型为 NGX_EVENT_MODULE 的模块总数
为每个事件模块分配唯一的 ctx_index(上下文索引),确保模块配置的存储和访问顺序一致


ngx_count_modules - NGX_EVENT_MODULE

ngx_count_modules - NGX_EVENT_MODULE-CSDN博客



此时 ngx_event_max_module=2


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

    *(void **) conf = ctx;

分配内存来存放指针 


ctx 是一个指针,指向的内容 *ctx 中存放一个指针,

*ctx 是数组,每个元素是一个指向 event 类型模块配置的指针

ctx 指针存放到全局配置数组中 ngx_events_module 模块对应的元素中


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

 通过 模块的 create_conf 函数创建 NGX_EVENT_MODULE 类型模块的配置结构体,

通过模块的 ctx_index  索引 将结构体的指针存放到 前面创建的指针数组 (*ctx)中对应的元素中


此次循环

modules[6]->name=ngx_event_core_module
的 create_conf 被调用

ctx_index=0

ngx_event_core_module 的 create_conf

ngx_event_core_module 的 create_conf-CSDN博客


modules[7]->name=ngx_epoll_module
的 create_conf 被调用

ctx_index=1

ngx_epoll_module 的 create_conf

ngx_epoll_module 的 create_conf-CSDN博客


    pcf = *cf;
    cf->ctx = ctx;
    cf->module_type = NGX_EVENT_MODULE;
    cf->cmd_type = NGX_EVENT_CONF;

    rv = ngx_conf_parse(cf, NULL);

    *cf = pcf;

    if (rv != NGX_CONF_OK) {
        return rv;
    }

 pcf = *cf;

保存当前配置解析上下文的原始状态

pcf 是 ngx_conf_t 类型的局部变量,用于临时存储当前的配置解析上下文。  
通过 *cf 将当前上下文完整复制到 pcf 中。  
意义:  
在解析 events 块时,需要临时修改配置解析上下文  
解析完成后,需恢复原始上下文,避免影响后续配置解析


cf->ctx = ctx;

设置当前配置上下文为事件模块的配置结构


cf->module_type = NGX_EVENT_MODULE;
声明当前处理的模块类型为事件模块。  
 module_type 是配置解析器的过滤条件,用于筛选出类型为 NGX_EVENT_MODULE 的模块。  

在解析指令时,只有标记为 NGX_EVENT_MODULE 的模块会被调用处理该指令。


cf->cmd_type = NGX_EVENT_CONF;
声明当前处理的配置指令类型为事件模块配置。  
cmd_type 进一步细化指令的类型,与模块定义的 ngx_command_t 中的 type 字段匹配。  

 确保只有支持 NGX_EVENT_CONF 类型的指令会被解析


 rv = ngx_conf_parse(cf, NULL);  
解析 events 块内的配置指令。   
调用 Nginx 的配置解析器,从当前文件位置开始解析 events 块内的指令。  
NULL 表示继续解析当前文件,而非新的文件。  
将 events 块内的指令分发到对应的事件模块处理函数(如设置连接数、选择事件模型等)。

ngx_conf_parse - events 块

ngx_conf_parse - events 块-CSDN博客


*cf = pcf;
恢复原始配置解析上下文。  
 
将之前保存的 pcf(原始上下文)重新赋值给 cf,覆盖临时修改的字段(如 ctx、module_type)。  
  


if (rv != NGX_CONF_OK) { return rv; }
检查配置解析结果并处理错误。  

如果 ngx_conf_parse 返回的 rv 不是 NGX_CONF_OK,说明解析失败(如无效指令或内存不足)。  
直接返回错误信息,终止当前配置解析流程。  


 

    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;
            }
        }
    }
遍历所有模块,跳过非事件模块
获取当前事件模块的上下文结构体(类型为ngx_event_module_t),其中包含模块的回调函数
检查并调用初始化函数 init_conf
设置未明确配置的参数的默认值

分别 调用了
cf->cycle->modules[6]->name=ngx_event_core_module 的 init_conf


cf->cycle->modules[7]->name=ngx_epoll_module 的 init_conf


ngx_event_core_module 的 init_conf

ngx_event_core_module 的 init_conf-CSDN博客


ngx_epoll_module 的 init_conf

ngx_epoll_module 的 init_conf-CSDN博客


return NGX_CONF_OK;

返回 表示处理成功

你可能感兴趣的:(nginx)