ngx_module_t结构体作为所有模块的通用接口
struct ngx_module_s {
ngx_uint_t ctx_index;
ngx_uint_t index;
char *name;
ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t version;
const char *signature;
void *ctx;
ngx_command_t *commands;
ngx_uint_t type;
ngx_int_t (*init_master)(ngx_log_t *log);
ngx_int_t (*init_module)(ngx_cycle_t *cycle);
ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t *cycle);
void (*exit_process)(ngx_cycle_t *cycle);
void (*exit_master)(ngx_cycle_t *cycle);
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;
};
index代表了在数组ngx_modules中的位置,ctx_index 同一大类间的子模块的位置,查看objs/nginx_modules.c,以一个ngx_module_t类型的数组定义了所有需要的模块,如下:
在定义实际的模块(ngx_module_s 只是一个抽象接口)时,以宏定义NGX_MODULE_V1 代替了ngx_module_t 上半部分成员,NGX_MODULE_V1_PADDING代替了ngx_module_t 下半部分成员
所以我认为不同的模块的定义实现,可以体现在在ctx,commands,type等成员的不同
struct ngx_module_s {
...
void *ctx;
ngx_command_t *commands;
ngx_uint_t type;
...
};
type定义为以下几种
#define NGX_CORE_MODULE 0x45524F43 /* "CORE" */
#define NGX_CONF_MODULE 0x464E4F43 /* "CONF" */
#define NGX_EVENT_MODULE 0x544E5645 /* "EVNT" */
#define NGX_HTTP_MODULE 0x50545448 /* "HTTP" */
根据不同type,就需要定义了不同的ctx及commands,举一个例子
type = NGX_CORE_MODULE 时
ctx定义为ngx_core_module_t:
typedef 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;
commands定义为ngx_command_t 类型的数组,以下是部分代码,省略了部分,从源码可以看出commands 管理模块的配置项
static ngx_command_t ngx_core_commands[] = {
{ ngx_string("daemon"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
0,
offsetof(ngx_core_conf_t, daemon),
NULL },
{ ngx_string("master_process"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
0,
offsetof(ngx_core_conf_t, master),
NULL },
{ ngx_string("timer_resolution"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
0,
offsetof(ngx_core_conf_t, timer_resolution),
NULL },
{ ngx_string("pid"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
0,
offsetof(ngx_core_conf_t, pid),
NULL },
....
}
下面是ngx_command_t结构体的说明(借用了《深入理解nginx框架》)
typedef struct ngx_command_s ngx_command_t;
struct ngx_command_s {
// 配置项名称,如 "gzip"
ngx_str_t name;
/*配置项类型, type将指定配置项可以出现的位置。例如,
出现在 server{}或 location{}中,以及它可以携带的参数个数 */
ngx_uint_t type;
// 出现了 name中指定的配置项后,将会调用 set方法处理配置项的参数
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
// 在配置文件中的偏移量
ngx_uint_t conf;
/*通常用于使用预设的解析方法解析配置项,这是配置模块的一个优秀设计。
它需要与 conf配合使用,在第 4章中详细介绍 */
ngx_uint_t offset;
// 配置项读取后的处理方法,必须是ngx_conf_post_t结构的指针
void *post;
};