1. 基本结构说明
1.1 模块基本结构
ngx_module_s 是 Nginx 对模块元信息的统一描述结构。每个模块在编译期以一个全局 ngx_module_t 实例存在,Nginx 启动时遍历 ngx_modules[] 数组,根据该结构体完成模块识别、初始化及生命周期管理。模块本身并不在运行时主动注册,而是由核心代码按模块类型和顺序进行统一调度。
其中,index 表示模块在全局模块数组 ngx_modules[] 中的唯一编号;ctx_index 表示模块在同类型模块上下文数组中的位置,用于快速定位模块私有配置。ctx 与 commands 描述模块的配置解析与处理能力,type 决定模块所属子系统(如 CORE / EVENT / HTTP)以及其参与的处理流程。init_* / exit_* 回调定义了模块在 master / worker 等不同生命周期阶段的初始化与退出行为,其余 spare 与 spare_hook 字段用于 ABI 兼容与扩展预留。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// 基本结构体
struct ngx_module_s {
ngx_uint_t ctx_index; /* 模块在 ctx 数组中的索引,用于 conf_ctx 查找模块配置 模块在“自己类型的模块上下文数组”里的编号。 比如它是第几个 HTTP 模块、第几个 EVENT 模块。 */
ngx_uint_t index; /* 模块在 ngx_modules[] 数组中的唯一编号 */
ngx_uint_t spare0; /* 备用字段(保留未用) */
ngx_uint_t spare1; /* 备用字段 */
ngx_uint_t spare2; /* 备用字段 */
ngx_uint_t spare3; /* 备用字段 */
ngx_uint_t version; /* Nginx 模块版本号(用于二进制兼容检查) */
void *ctx; /* 模块上下文指针(模块专用数据/回调集合) */
ngx_command_t *commands; /* 模块可用指令列表(解析 nginx.conf) */
ngx_uint_t type; /* 模块类型(NGX_CORE_MODULE/NGX_HTTP_MODULE/NGX_HTTP_FILTER_MODULE 等) */
ngx_int_t (*init_master)(ngx_log_t *log); /* master 进程初始化时调用 */
ngx_int_t (*init_module)(ngx_cycle_t *cycle);/* 模块全局初始化(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 进程退出回调 */
uintptr_t spare_hook0; /* 备用 hook 字段 */
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;
};
// 2. 模块定义 & 初始化
ngx_module_t ngx_http_hello_module = {
NGX_MODULE_V1, // #define NGX_MODULE_V1 0, 0, 0, 0, 0, 0, 1
&ngx_http_hello_module_ctx, /* module context */
ngx_http_hello_commands, /* module directives */
NGX_HTTP_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
};
1.2 模块上下文指针
ctx 是模块与具体子系统(CORE / EVENT / HTTP 等)交互的关键入口。它并不是一个固定类型,而是一个 void *,在不同模块类型下指向不同的上下文结构体。例如 HTTP 模块中,ctx 实际指向一个 ngx_http_module_t 结构,用于向 HTTP 核心注册配置创建、合并以及配置解析前后的回调函数。
对于 HTTP 模块而言,ngx_http_module_t 定义了三层配置(main / srv / loc)的创建与合并逻辑,并允许模块在配置解析前后插入自定义处理流程。Nginx 在解析 nginx.conf 时,会根据模块类型对 ctx 进行强制类型转换,并按既定时机调用其中的回调函数,从而完成模块配置对象的生命周期管理。
` void ctx; / 模块上下文指针(模块专用数据/回调集合) / &ngx_http_hello_module_ctx, / module context */`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
typedef struct {
ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
ngx_int_t (*postconfiguration)(ngx_conf_t *cf);
void *(*create_main_conf)(ngx_conf_t *cf);
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
void *(*create_srv_conf)(ngx_conf_t *cf);
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);
void *(*create_loc_conf)(ngx_conf_t *cf);
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;
// 模块上下文
static ngx_http_module_t ngx_http_hello_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
1.3 Command 指针
commands 指向模块支持的配置指令表,用于在解析 nginx.conf 时将文本指令映射为模块行为。每个 ngx_command_t 描述一条指令的名称、适用作用域及解析方式,HTTP 核心在配置阶段遍历该表,根据指令出现的位置调用对应的 set 回调完成配置或注册处理逻辑。
对于 HTTP 模块而言,指令通常在 location / server / http 等上下文中生效,其解析过程完全由 ngx_command_t 表驱动,模块只需提供指令描述与回调函数即可,无需关心配置文件的遍历与调度细节。
ngx_http_hello_commands, /* module directives */ ngx_command_t *commands; /* 模块可用指令列表(解析 nginx.conf) */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 定义指令(例如 hello)
static ngx_command_t ngx_http_hello_commands[] = {
{
ngx_string("hello"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_http_hello,
0,
0,
NULL
},
ngx_null_command
};
struct ngx_command_s {
ngx_str_t name;
ngx_uint_t type;
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
ngx_uint_t conf;
ngx_uint_t offset;
void *post;
};