当前位置: 首页 > 工具软件 > ngx-treeview > 使用案例 >

nginx源码初读(11)--让烦恼从数据结构开始(ngx_command/ngx_module/ngx_conf)

高正初
2023-12-01

第一点:ngx_command_t
ngx_core_commands是nginx中的核心模块指令, 它的类型就是ngx_command_t。在每一个module的结构体中,也都有一个ngx_command_t。

typedef struct ngx_command_s     ngx_command_t;

struct ngx_command_s {
    ngx_str_t             name;            // 配置指令的名称
    ngx_uint_t            type;            // 配置指令的类型(参数个数描述等)
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    /*  当nginx在解析配置的时候,如果遇到这个配置指令,将会把读取到的值传递给这个函数进行解析保存。
        因为具体每个配置指令的值如何处理,只有定义这个配置指令的人是最清楚的,set可能复杂也可能很简单。
        比如errlog模块的“error_log”指令就是调用ngx_error_log写一条日志,并不需要存储什么配置数据。
     *  cf: 保存从配置文件读取到的原始字符串以及相关信息。这个参数的args字段是一个ngx_str_t类型的数组,
            该数组首元素是这个配置指令本身,第二个元素开始才是参数。
        cmd: 这个配置指令对应的ngx_command_t结构。
        conf: 就是定义的存储这个配置值的结构体
     */   

    ngx_uint_t            conf;
    /* 该字段被NGX_HTTP_MODULE类型模块所用,指定当前配置项存储的内存位置。实际上是使用哪个内存池的问题。
       因为http模块对所有http模块所要保存的配置信息,划分了main, server和location三个地方进行存储,
       每个地方都有一个内存池用来分配存储这些信息的内存。
       这里可能的值为NGX_HTTP_MAIN_CONF_OFFSET、NGX_HTTP_SRV_CONF_OFFSET或NGX_HTTP_LOC_CONF_OFFSET。
       当然也可以直接置为0,就是NGX_HTTP_MAIN_CONF_OFFSET。 
     */   

    ngx_uint_t            offset; 
    /* 指定该配置项值的精确存放位置,一般指定为某一个结构体变量的字段偏移。
       比如我们定义了一个结构体A,该项配置的值需要存储到该结构体的b字段。那么在这里就可以填写offsetof(A, b)。
       对于有些配置项,它的值不需要保存或者是需要保存到更为复杂的结构中时,这里可以设置为0。 
     */  

    void                 *post; 
    /* 可指向任何一个在读取配置过程中需要的数据,以便于进行配置读取的处理。大多时候不需要,设为0即可。*/
};

static ngx_command_t  ngx_core_commands[];   // 保存了核心指令

第二点:ngx_module_t
对于开发一个模块来说,我们都需要定义一个ngx_module_t类型的变量来说明这个模块本身的信息,从某种意义上来说,这是这个模块最重要的一个信息。它告诉了nginx这个模块的一些信息,上面定义的配置信息,还有模块上下文信息,都是通过这个结构来告诉nginx系统的,也就是加载模块的上层代码,都需要通过定义的这个结构,来获取这些信息。

typedef struct ngx_module_s      ngx_module_t;
struct ngx_module_s {
    ngx_uint_t            ctx_index;
    /* 在相应模块类的计数,nginx模块分为四种:core、event、http和mail
     * ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
     */

    ngx_uint_t            index;
    /* 模块计数器,按照每个模块在ngx_modules[]数组中的声明顺序,从0开始依次给每个模块赋值 */

    ngx_uint_t            spare0;
    ngx_uint_t            spare1;
    ngx_uint_t            spare2;
    ngx_uint_t            spare3;


    ngx_uint_t            version;     
    /* 模块当前版本 */

    void                 *ctx;
    /* 模块上下文,不同类别模块有不同上下文,ngx_http_conf_ctx_t/ngx_mail_conf_ctx_t/... */

    ngx_command_t        *commands; 
    /* 该模块的命令集,是ngx_command_t数组 */

    ngx_uint_t            type; 
    /* 模块种类:core、event、http和mail */

    ngx_int_t           (*init_master)(ngx_log_t *log);           // master进程初始化调用
    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);       // 模块初始化调用
    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);      // worker进程初始化调用
    ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);       // 线程初始化调用
    void                (*exit_thread)(ngx_cycle_t *cycle);       // 线程退出调用
    void                (*exit_process)(ngx_cycle_t *cycle);      // worker进程结束调用
    void                (*exit_master)(ngx_cycle_t *cycle);       // master进程结束调用
    /* callback:如果该模块需要发生这些行为执行特定的功能,可以通过这些回调函数指针注册一个回调函数接口来实现 */

    uintptr_t             spare_hook0;
    uintptr_t             spare_hook1;
    uintptr_t             spare_hook2;
    uintptr_t             spare_hook3;
    uintptr_t             spare_hook4;
    uintptr_t             spare_hook5;
    uintptr_t             spare_hook6;
    uintptr_t             spare_hook7;
};


#define NGX_NUMBER_MAJOR  3
#define NGX_NUMBER_MINOR  1

#define NGX_MODULE_V1          0, 0, 0, 0,                              \
    NGX_DSO_ABI_COMPATIBILITY, NGX_NUMBER_MAJOR, NGX_NUMBER_MINOR
    /* 前7个成员初始化 */

#define NGX_MODULE_V1_PADDING  0, 0, 0, 0, 0, 0, 0, 0 
    /* 后8个成员初始化 */

第三点:ngx_conf_t
该结构体用于Nginx在解析配置文件时描述每个指令的属性,是Nginx程序中非常重要的一个数据结构。

typedef struct {
    ngx_file_t            file;            // 文件
    ngx_buf_t            *buffer;          // 文件内容
    ngx_uint_t            line;            // 文件行数
} ngx_conf_file_t;

typedef char *(*ngx_conf_handler_pt)(ngx_conf_t *cf,
    ngx_command_t *dummy, void *conf);

typedef struct ngx_conf_s   ngx_conf_t
struct ngx_conf_s {
    char                 *name;            // 存放当前解析到的指令 

    ngx_array_t          *args;            // 从配置中读取指令的名称和相对应的参数

    ngx_cycle_t          *cycle;           // 对应的cycle(一个进程有一个cycle)
    ngx_pool_t           *pool;            // 对应的内存池
    ngx_pool_t           *temp_pool;       // 临时内存池,在解析配置文件的时候使用,之后释放了
    ngx_conf_file_t      *conf_file;       // 配置文件的信息
    ngx_log_t            *log;             // 对应的log

    void                 *ctx;             // 上下文(指向模块配置信息)
    ngx_uint_t            module_type;     // 处理当前指令的模块类型:core、event、mail和http
    ngx_uint_t            cmd_type;        // 当前指令的类型

    ngx_conf_handler_pt   handler;         // 自定义的指令处理函数
    char                 *handler_conf;    // 作为handler的参数,提供一些handler需要的配置信息
};

至此,基本的数据结构都看完了,开始学流程和机制吧!

 类似资料: