nginx源码分析(2)——http模块的初始化过程

本文详细探讨了nginx http模块的初始化过程,包括ngx_http_module_t数据结构及其在配置继承和覆盖中的作用,以及配置文件解析时对Http、Server和Location块的深度优先遍历。重点介绍了ngx_http_block在http块解析中的关键步骤,如ngx_http_core_module的配置指令和服务器、位置块的初始化。
摘要由CSDN通过智能技术生成

        前一篇文章介绍了nginx的启动初始化过程,包括了所有模块的初始化过程,比如http模块、事件模块等。这里再详细介绍一下http模块的启动过程,还记得在前一篇文章中提到过ngx_conf_parse函数背后隐藏了大量的细节吗?这里就揭开这层神秘的面纱,去看看几个重要的http模块是如何初始化的。这里依然沿用上一篇文章的结构,首先来看几个重要的数据结构。

1. 重要的数据结构

        1. ngx_http_module_t

        所有http模块都是ngx_http_module_t类型,所有的属性都是回调函数,在http模块初始化过程的不同阶段调用。当一个指令既允许出现在main块(在http{}块内,但是在server{}块外的区域)、server块(在server{}块内,但是在location{}块外的区域)、location块内时,就需要对这些指令进行继承和覆盖的处理,由merge_src_conf和merge_loc_conf完成。

typedef struct {
    /**
     * 在解析配置文件中http{}配置块前调用
     */
    ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);

    /**
     * 在解析配置文件中http{}配置块后调用
     */
    ngx_int_t   (*postconfiguration)(ngx_conf_t *cf);

    /**
     * 创建http模块的main config
     */
    void       *(*create_main_conf)(ngx_conf_t *cf);
    
    /**
     * 初始化http模块的main config
     */
    char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);

    /**
     * 创建http模块的server config
     */
    void       *(*create_srv_conf)(ngx_conf_t *cf);
    
    /**
     * 合并http模块的server config,用于实现server config到main config的指令的继承、覆盖
     */
    char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);

    /**
     * 创建http模块的location config
     */
    void       *(*create_loc_conf)(ngx_conf_t *cf);
    
    /**
     * 合并http模块的location config,用于实现location config到server config的指令的继承、覆盖
     */
    char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;

        2. ngx_http_conf_ctx_t

        此结构用于保存所有http模块的main、server和location的config结构。可以看到ngx_http_conf_ctx_t的三个属性就是三个数组,数组大小由ngx_http_max_module指定的,这个变量在指令http块的回调函数时初始化。还记得在上一篇介绍的ngx_module_t结构的ctx_index属性吗?对于一个http模块,ctx_index属性就指示了该模块的main、srv和loc的config结构在这三个数组中的下标。

typedef struct {
    /**
     * 所有模块的main config数组
     */
    void        **main_conf;

    /**
     * 所有模块的server config数组
     */
    void        **srv_conf;

    /**
     * 所有模块的location config数组
     */
    void        **loc_conf;
} ngx_http_conf_ctx_t;
        在我们编写http模块时,经常要获取模块的main、srv和loc配置信息,nginx提供了两类宏来处理:

        在处理请求时,可以通过:

#define ngx_http_get_module_main_conf(r, module)                             \
    (r)->main_conf[module.ctx_index]
#define ngx_http_get_module_srv_conf(r, module)  (r)->srv_conf[module.ctx_index]
#define ngx_http_get_module_loc_conf(r, module)  (r)->loc_conf[module.ctx_index]

        实现起来很简单只要传入的r是ngx_http_request_t类型的,module就是对应的模块,直接通过ctx_index索引就可以获取到对应配置结构。

        在解析配置文件过程,通常用在指令的set回调函数中:

#define ngx_http_conf_get_module_main_conf(cf, module)                        \
    ((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]
#define ngx_http_conf_get_module_srv_conf(cf, module)                         \
    ((ngx_http_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index]
#define ngx_http_conf_get_module_loc_conf(cf, module)                         \
    ((ngx_http_conf_ctx_t *) cf->ctx)->loc_conf[module.ctx_index]
        cf是ngx_conf_t类型,module同样是对应的模块。

2. http模块的启动过程

        前文已经提到了nginx配置文件解析时,会首先解析core module,然后由core module再去解析相应类型的module,比如由ngx_http_module(这是一个core module)负责解析所有的http module,而由ngx_events_module(也是一个core module)解析所有的event module。如果把配置文件看成一棵树:
               Main
              /           \

               Events         Http

                                      /          \

                                     Server          Server

                                    /             \                   \

                                      Location     Location      Location

        这棵树中,每个节点对应一个配置块,配置文件的解析就是对这棵树的深度优先遍历,并对每个节点调用ngx_conf_parse函数。其中的Http节点对应的就是ngx_http_module模块,是由它驱动后面的server块和location块的解析,其他的细节部分会在nginx配置文件解析中讲解。下面先来看一下ngx_http_module的结构:

static ngx_command_t  ngx_http_commands[] = {

    { ngx_string("http"),
      NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_http_block,
      0,
      0,
      NULL },

      ngx_null_command
};

static ngx_core_module_t  ngx_http_module_ctx = {
    ngx_string("http"),
    NULL,
    NULL
};

ngx_module_t  ngx_http_module = {
    NGX_MODULE_V1,
    &ngx_http_module_ctx,                  /* module context */
    ngx_http_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_http_module模块只有一个http指令,也就是http{},这个指令的回调函数是ngx_http_block,而且它的类型中有NGX_CONF_BLOCK,所以这个模块会在解析所有core module时,在配置文件中遇到http{}块时被调用。也就是说http模块的初始化的入口就是ngx_http_block,下面具体看一下这个函数
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值