前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >nginx0.1.0之event模块初始化源码分析(1)

nginx0.1.0之event模块初始化源码分析(1)

作者头像
theanarkh
发布2019-03-06 10:59:27
4590
发布2019-03-06 10:59:27
举报
文章被收录于专栏:原创分享原创分享

下面是nginx中几个重要的数据结构。

代码语言:javascript
复制
struct ngx_command_s {
    ngx_str_t     name; // 命令名字
    int           type; // 命令的属性,参数个数、上下文等
    char       *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); // 处理该命令的函数
    int           conf;
    int           offset;
    void         *post;
};

struct {
    ngx_str_t       name;
    void         *(*create_conf)(ngx_cycle_t *cycle);
    char         *(*init_conf)(ngx_cycle_t *cycle, void *conf);
} ngx_core_module_t; 

struct ngx_module_s {
    ngx_uint_t       ctx_index;
    ngx_uint_t       index;
    void            *ctx;
    ngx_command_t   *commands;
    ngx_uint_t       type;
    ngx_int_t      (*init_module)(ngx_cycle_t *cycle);
    ngx_int_t      (*init_process)(ngx_cycle_t *cycle);
#if 0
    ngx_int_t      (*init_thread)(ngx_cycle_t *cycle);
#endif
};

下面是event模块的配置

代码语言:javascript
复制
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
};


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


ngx_module_t  ngx_events_module = {
    NGX_MODULE,
    &ngx_events_module_ctx,                /* module context */
    ngx_events_commands,                   /* module directives */
    NGX_CORE_MODULE,                       /* module type */
    NULL,                                  /* init module */
    NULL                                   /* init process */
};

nginx模块初始化的流程在下面的代码中,核心模块的初始化,各核心模块首先在create_conf中创建保存配置的数据结构,然后在ngx_conf_parse中,通过解析命令,执行对应的命令处理函数,完成赋值和各核心模块的子模块初始化。最后,如果在ngx_conf_parse时,没有设置值,则执行init_conf函数进行默认初始化。

代码语言:javascript
复制
// 执行核心模块的钩子函数,该版本只有ngx_core_module模块定义了这个钩子
    for (i = 0; ngx_modules[i]; i++) {
        if (ngx_modules[i]->type != NGX_CORE_MODULE) {
            continue;
        }

        module = ngx_modules[i]->ctx;
        // 用于存储各类型模块下子模块的配置
        if (module->create_conf) {
            // 分配一块内存存储子模块的数据结构,如ngx_core_module_create_conf函数
            rv = module->create_conf(cycle);
            if (rv == NGX_CONF_ERROR) {
                ngx_destroy_pool(pool);
                return NULL;
            }
            cycle->conf_ctx[ngx_modules[i]->index] = rv;
        }
    }

    // 初始化保存指令信息的结构体
    ngx_memzero(&conf, sizeof(ngx_conf_t));
    /* STUB: init array ? */
    conf.args = ngx_create_array(pool, 10, sizeof(ngx_str_t));
    if (conf.args == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }
    // 指向所有模块的上下文
    conf.ctx = cycle->conf_ctx;
    conf.cycle = cycle;
    conf.pool = pool;
    conf.log = log;
    conf.module_type = NGX_CORE_MODULE;
    conf.cmd_type = NGX_MAIN_CONF;

    // 解析配置文件,把结果写入conf
    if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
        ngx_destroy_pool(pool);
        return NULL;
    }

    for (i = 0; ngx_modules[i]; i++) {
        if (ngx_modules[i]->type != NGX_CORE_MODULE) {
            continue;
        }

        module = ngx_modules[i]->ctx;
        // 如ngx_core_module_init_conf函数
        if (module->init_conf) {
            // cycle->conf_ctx[ngx_modules[i]->index]由crete_init函数创建
            if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])
                                                              == NGX_CONF_ERROR)
            {
                ngx_destroy_pool(pool);
                return NULL;
            }
        }
    }
... // 配置处理完,开始初始化各个模块
    for (i = 0; ngx_modules[i]; i++) {
        if (ngx_modules[i]->init_module) {
            if (ngx_modules[i]->init_module(cycle) == NGX_ERROR) {
                /* fatal */
                exit(1);
            }
        }
    }

从上面的代码中我们知道event模块没有实现create_conf和init_conf函数,那么event模块初始化的时机是什么时候?答案是在解析到event命令的时候。由event模块对应的配置可知,当解析到event命令的时候,会执行ngx_events_block函数。代码如下。

代码语言:javascript
复制
static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    int                    m;
    char                  *rv;
    void               ***ctx;
    ngx_conf_t            pcf;
    ngx_event_module_t   *module;

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

    ngx_event_max_module = 0;
    // 初始化每个子模块的序号
    for (m = 0; ngx_modules[m]; m++) {
        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
            continue;
        }

        ngx_modules[m]->ctx_index = ngx_event_max_module++;
    }
    // ctx指向一个指针
    ngx_test_null(ctx, ngx_pcalloc(cf->pool, sizeof(void *)), NGX_CONF_ERROR);
    // ctx指向的指针再指向一个指针数组
    ngx_test_null(*ctx,
                  ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *)),
                  NGX_CONF_ERROR);
    // event是NGX_MAIN_CONF类型的模块,conf为四级指针
    *(void **) conf = ctx;

    for (m = 0; ngx_modules[m]; m++) {
        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
            continue;
        }
        // event类型的模块的ctx
        module = ngx_modules[m]->ctx;
        // 把create_conf返回的数据结构存储在上面开辟的数组里
        if (module->create_conf) {
            ngx_test_null((*ctx)[ngx_modules[m]->ctx_index],
                          module->create_conf(cf->cycle),
                          NGX_CONF_ERROR);
        }
    }
    // event模块都是基于下面的上下文配置进行命令的解析
    pcf = *cf;
    // 修改当前的上下文和作用域信息
    cf->ctx = ctx;
    // 用于过滤模块类型,即接下来的配置解析中,等于该类型的模块才能处理该命令
    cf->module_type = NGX_EVENT_MODULE;
    /*
        解析出一个配置的时候,如果匹配到了某个命令配置,则该命令配置是否是属于NGX_EVENT_CONF类型,
        用于二级 过滤,即过滤掉同模块里的不符合条件的模块
    */
    cf->cmd_type = NGX_EVENT_CONF;
    // 继续解析,对event模块的子模块的字段进行赋值
    rv = ngx_conf_parse(cf, NULL);
    *cf = pcf;

    if (rv != NGX_CONF_OK)
        return rv;
    // 如果ngx_conf_parse没有进行赋值,则执行init_conf函数时进行默认初始化
    for (m = 0; ngx_modules[m]; m++) {
        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
            continue;
        }

        module = ngx_modules[m]->ctx;
        // 初始化create_conf创建的结构体
        if (module->init_conf) {
            // 如果在ngx_conf_parse里没有对模块的配置进行初始化则这里进行默认初始化,一般是在cmd的set函数进行初始化
            rv = module->init_conf(cf->cycle,
                                   (*ctx)[ngx_modules[m]->ctx_index]);
            if (rv != NGX_CONF_OK) {
                return rv;
            }
        }
    }

    return NGX_CONF_OK;
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程杂技 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档