Nginx源码解读-module

前言

模块化是Nginx的一个重要特性,一方面可以很好的拆解各功能之间的耦合,另一方便让Nginx的扩展性得到很大提升。每个人都可以开发模块来适应实际遇到的场景。后面会有专门的一篇来介绍Nginx的模块开发工作,本篇则主要是介绍Nginx模块的内部结构,只有在完全了解这些的基础上,我们在开发模块的时候才能得心应手。相关代码参照src/core/ngx_module.h|.c

数据结构

宏操作

值定义

模块未使用情况下成员index的值,也适用于ctx_index

1
#define NGX_MODULE_UNSET_INDEX  (ngx_uint_t) -1

模块上限

在Nginx中,模块分为静态模块动态模块。其中对于动态模块是有一个数量的限制,不能超过NGX_MAX_DYNAMIC_MODULES,也就是128个。

1
#define NGX_MAX_DYNAMIC_MODULES  128

模块签名

模块的签名组成是据编译时各种环境、开关条件,总共35组,最终的签名则是这35项的一个集合

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#define NGX_MODULE_SIGNATURE_0                                                \
ngx_value(NGX_PTR_SIZE) "," \
ngx_value(NGX_SIG_ATOMIC_T_SIZE) "," \
ngx_value(NGX_TIME_T_SIZE) ","

#if (NGX_HAVE_KQUEUE)
#define NGX_MODULE_SIGNATURE_1 "1"
#else
#define NGX_MODULE_SIGNATURE_1 "0"
#endif

#if (NGX_HAVE_IOCP)
#define NGX_MODULE_SIGNATURE_2 "1"
#else
#define NGX_MODULE_SIGNATURE_2 "0"
#endif

#if (NGX_HAVE_FILE_AIO || NGX_COMPAT)
#define NGX_MODULE_SIGNATURE_3 "1"
#else
#define NGX_MODULE_SIGNATURE_3 "0"
#endif

#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT)
#define NGX_MODULE_SIGNATURE_4 "1"
#else
#define NGX_MODULE_SIGNATURE_4 "0"
#endif

#if (NGX_HAVE_EVENTFD)
#define NGX_MODULE_SIGNATURE_5 "1"
#else
#define NGX_MODULE_SIGNATURE_5 "0"
#endif

#if (NGX_HAVE_EPOLL)
#define NGX_MODULE_SIGNATURE_6 "1"
#else
#define NGX_MODULE_SIGNATURE_6 "0"
#endif

#if (NGX_HAVE_KEEPALIVE_TUNABLE)
#define NGX_MODULE_SIGNATURE_7 "1"
#else
#define NGX_MODULE_SIGNATURE_7 "0"
#endif

#if (NGX_HAVE_INET6)
#define NGX_MODULE_SIGNATURE_8 "1"
#else
#define NGX_MODULE_SIGNATURE_8 "0"
#endif

#define NGX_MODULE_SIGNATURE_9 "1"
#define NGX_MODULE_SIGNATURE_10 "1"

#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
#define NGX_MODULE_SIGNATURE_11 "1"
#else
#define NGX_MODULE_SIGNATURE_11 "0"
#endif

#define NGX_MODULE_SIGNATURE_12 "1"

#if (NGX_HAVE_SETFIB)
#define NGX_MODULE_SIGNATURE_13 "1"
#else
#define NGX_MODULE_SIGNATURE_13 "0"
#endif

#if (NGX_HAVE_TCP_FASTOPEN)
#define NGX_MODULE_SIGNATURE_14 "1"
#else
#define NGX_MODULE_SIGNATURE_14 "0"
#endif

#if (NGX_HAVE_UNIX_DOMAIN)
#define NGX_MODULE_SIGNATURE_15 "1"
#else
#define NGX_MODULE_SIGNATURE_15 "0"
#endif

#if (NGX_HAVE_VARIADIC_MACROS)
#define NGX_MODULE_SIGNATURE_16 "1"
#else
#define NGX_MODULE_SIGNATURE_16 "0"
#endif

#define NGX_MODULE_SIGNATURE_17 "0"
#define NGX_MODULE_SIGNATURE_18 "0"

#if (NGX_HAVE_OPENAT)
#define NGX_MODULE_SIGNATURE_19 "1"
#else
#define NGX_MODULE_SIGNATURE_19 "0"
#endif

#if (NGX_HAVE_ATOMIC_OPS)
#define NGX_MODULE_SIGNATURE_20 "1"
#else
#define NGX_MODULE_SIGNATURE_20 "0"
#endif

#if (NGX_HAVE_POSIX_SEM)
#define NGX_MODULE_SIGNATURE_21 "1"
#else
#define NGX_MODULE_SIGNATURE_21 "0"
#endif

#if (NGX_THREADS || NGX_COMPAT)
#define NGX_MODULE_SIGNATURE_22 "1"
#else
#define NGX_MODULE_SIGNATURE_22 "0"
#endif

#if (NGX_PCRE)
#define NGX_MODULE_SIGNATURE_23 "1"
#else
#define NGX_MODULE_SIGNATURE_23 "0"
#endif

#if (NGX_HTTP_SSL || NGX_COMPAT)
#define NGX_MODULE_SIGNATURE_24 "1"
#else
#define NGX_MODULE_SIGNATURE_24 "0"
#endif

#define NGX_MODULE_SIGNATURE_25 "1"

#if (NGX_HTTP_GZIP)
#define NGX_MODULE_SIGNATURE_26 "1"
#else
#define NGX_MODULE_SIGNATURE_26 "0"
#endif

#define NGX_MODULE_SIGNATURE_27 "1"

#if (NGX_HTTP_X_FORWARDED_FOR)
#define NGX_MODULE_SIGNATURE_28 "1"
#else
#define NGX_MODULE_SIGNATURE_28 "0"
#endif

#if (NGX_HTTP_REALIP)
#define NGX_MODULE_SIGNATURE_29 "1"
#else
#define NGX_MODULE_SIGNATURE_29 "0"
#endif

#if (NGX_HTTP_HEADERS)
#define NGX_MODULE_SIGNATURE_30 "1"
#else
#define NGX_MODULE_SIGNATURE_30 "0"
#endif

#if (NGX_HTTP_DAV)
#define NGX_MODULE_SIGNATURE_31 "1"
#else
#define NGX_MODULE_SIGNATURE_31 "0"
#endif

#if (NGX_HTTP_CACHE)
#define NGX_MODULE_SIGNATURE_32 "1"
#else
#define NGX_MODULE_SIGNATURE_32 "0"
#endif

#if (NGX_HTTP_UPSTREAM_ZONE)
#define NGX_MODULE_SIGNATURE_33 "1"
#else
#define NGX_MODULE_SIGNATURE_33 "0"
#endif

#if (NGX_COMPAT)
#define NGX_MODULE_SIGNATURE_34 "1"
#else
#define NGX_MODULE_SIGNATURE_34 "0"
#endif

/* 模块签名 */
#define NGX_MODULE_SIGNATURE \
NGX_MODULE_SIGNATURE_0 NGX_MODULE_SIGNATURE_1 NGX_MODULE_SIGNATURE_2 \
NGX_MODULE_SIGNATURE_3 NGX_MODULE_SIGNATURE_4 NGX_MODULE_SIGNATURE_5 \
NGX_MODULE_SIGNATURE_6 NGX_MODULE_SIGNATURE_7 NGX_MODULE_SIGNATURE_8 \
NGX_MODULE_SIGNATURE_9 NGX_MODULE_SIGNATURE_10 NGX_MODULE_SIGNATURE_11 \
NGX_MODULE_SIGNATURE_12 NGX_MODULE_SIGNATURE_13 NGX_MODULE_SIGNATURE_14 \
NGX_MODULE_SIGNATURE_15 NGX_MODULE_SIGNATURE_16 NGX_MODULE_SIGNATURE_17 \
NGX_MODULE_SIGNATURE_18 NGX_MODULE_SIGNATURE_19 NGX_MODULE_SIGNATURE_20 \
NGX_MODULE_SIGNATURE_21 NGX_MODULE_SIGNATURE_22 NGX_MODULE_SIGNATURE_23 \
NGX_MODULE_SIGNATURE_24 NGX_MODULE_SIGNATURE_25 NGX_MODULE_SIGNATURE_26 \
NGX_MODULE_SIGNATURE_27 NGX_MODULE_SIGNATURE_28 NGX_MODULE_SIGNATURE_29 \
NGX_MODULE_SIGNATURE_30 NGX_MODULE_SIGNATURE_31 NGX_MODULE_SIGNATURE_32 \
NGX_MODULE_SIGNATURE_33 NGX_MODULE_SIGNATURE_34

辅助初始化

为了方便模块的快速初始化,减少开发人员不必要的劳动,Nginx定义了NGX_MODULE_V1NGX_MODULE_V1_PADDING这两个宏

1
2
3
4
5
#define NGX_MODULE_V1                                                         \
NGX_MODULE_UNSET_INDEX, NGX_MODULE_UNSET_INDEX, \
NULL, 0, 0, nginx_version, NGX_MODULE_SIGNATURE

#define NGX_MODULE_V1_PADDING 0, 0, 0, 0, 0, 0, 0, 0

普通模块

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
52
53
54
55
56
57
58
59
60
struct ngx_module_s {

/* 扩展index */
ngx_uint_t ctx_index;

/* 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;

/* master初始化时调用 */
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);

/* master进程退出时调用 */
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;
};

以上就是一个完整的Nginx模块的结构了,其中有一部分数据成员是很少用到的,在后面的模块开发过程中我们会看到利用NGX_MODULE_V1,NGX_MODULE_V1_PADDING定义的宏来帮助我们完成模块的初始化。

核心模块

1
2
3
4
5
6
7
8
9
10
11
/* 核心模块 */
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;

主要方法

ngx_module_index

从模块中获取一个未被使用的index

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
static ngx_uint_t
ngx_module_index(ngx_cycle_t *cycle)
{
ngx_uint_t i, index;
ngx_module_t *module;

index = 0;

again:

/* find an unused index */

for (i = 0; cycle->modules[i]; i++) {
module = cycle->modules[i];

/* 如果该index被用的了话 就要从头判断index+1是否被占用了 */
if (module->index == index) {
index++;
goto again;
}
}

/* check previous cycle */

if (cycle->old_cycle && cycle->old_cycle->modules) {

for (i = 0; cycle->old_cycle->modules[i]; i++) {
module = cycle->old_cycle->modules[i];

/* 如果该index被用的了话 就要从头判断index+1是否被占用了 */
if (module->index == index) {
index++;
goto again;
}
}
}

return index;
}

ngx_module_ctx_index

ngx_module_index方法类似,从模块中获取一个未被使用的ctx_index,这两个方法基本一致,就不多加注释了,可以参照上面。

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
static ngx_uint_t
ngx_module_ctx_index(ngx_cycle_t *cycle, ngx_uint_t type, ngx_uint_t index)
{
ngx_uint_t i;
ngx_module_t *module;

again:

/* find an unused ctx_index */

for (i = 0; cycle->modules[i]; i++) {
module = cycle->modules[i];

if (module->type != type) {
continue;
}

if (module->ctx_index == index) {
index++;
goto again;
}
}

/* check previous cycle */

if (cycle->old_cycle && cycle->old_cycle->modules) {

for (i = 0; cycle->old_cycle->modules[i]; i++) {
module = cycle->old_cycle->modules[i];

if (module->type != type) {
continue;
}

if (module->ctx_index == index) {
index++;
goto again;
}
}
}

return index;
}

ngx_preinit_modules

预初始化各个模块,主要功能是确定每个模块的indexname属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ngx_int_t
ngx_preinit_modules(void)
{
ngx_uint_t i;

for (i = 0; ngx_modules[i]; i++) {
ngx_modules[i]->index = i;
ngx_modules[i]->name = ngx_module_names[i];
}

ngx_modules_n = i;

/* 最大木块数量 = 静态的模块数量 + 最大动态模块数量 */
ngx_max_module = ngx_modules_n + NGX_MAX_DYNAMIC_MODULES;

return NGX_OK;
}

ngx_cycle_modules

把一组模块拷贝到cycle中去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ngx_int_t
(ngx_cycle_t *cycle)
{
/*
* create a list of modules to be used for this cycle,
* copy static modules to it
*/

/* 申请存储模块的空间 */
cycle->modules = ngx_pcalloc(cycle->pool, (ngx_max_module + 1)
* sizeof(ngx_module_t *));
if (cycle->modules == NULL) {
return NGX_ERROR;
}

/* 拷贝模块 */
ngx_memcpy(cycle->modules, ngx_modules,
ngx_modules_n * sizeof(ngx_module_t *));

/* 设置模块数量 */
cycle->modules_n = ngx_modules_n;

return NGX_OK;
}

ngx_init_modules

调用每个模块的初始化方法完成模块的初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ngx_int_t
ngx_init_modules(ngx_cycle_t *cycle)
{
ngx_uint_t i;

/* 确保每个模块有初始化方法并调用 */
for (i = 0; cycle->modules[i]; i++) {
if (cycle->modules[i]->init_module) {
if (cycle->modules[i]->init_module(cycle) != NGX_OK) {
return NGX_ERROR;
}
}
}

return NGX_OK;
}

ngx_count_modules

确定满足tag的模块中的下一个可用ctx_index的值

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
ngx_int_t
ngx_count_modules(ngx_cycle_t *cycle, ngx_uint_t type)
{
ngx_uint_t i, next, max;
ngx_module_t *module;

next = 0;
max = 0;

/* count appropriate modules, set up their indices */

for (i = 0; cycle->modules[i]; i++) {
module = cycle->modules[i];

/* tag不满足 */
if (module->type != type) {
continue;
}

/* 模块已经使用了 */
if (module->ctx_index != NGX_MODULE_UNSET_INDEX) {

/* if ctx_index was assigned, preserve it */

if (module->ctx_index > max) {
max = module->ctx_index;
}

if (module->ctx_index == next) {
next++;
}

continue;
}

/* search for some free index */
/* 模块还未使用 需要先确定当前模块的ctx_index */
module->ctx_index = ngx_module_ctx_index(cycle, type, next);

if (module->ctx_index > max) {
max = module->ctx_index;
}

next = module->ctx_index + 1;
}

ngx_add_module

往模块数组中添加一个新的模块

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
ngx_int_t
ngx_add_module(ngx_conf_t *cf, ngx_str_t *file, ngx_module_t *module,
char **order)
{
void *rv;
ngx_uint_t i, m, before;
ngx_core_module_t *core_module;

/* 判断已加载的模块数量是否达到上限 */
if (cf->cycle->modules_n >= ngx_max_module) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"too many modules loaded");
return NGX_ERROR;
}

/* 判断版本是否一致 */
if (module->version != nginx_version) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"module \"%V\" version %ui instead of %ui",
file, module->version, (ngx_uint_t) nginx_version);
return NGX_ERROR;
}

/* 判断签名是否一致 */
if (ngx_strcmp(module->signature, NGX_MODULE_SIGNATURE) != 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"module \"%V\" is not binary compatible",
file);
return NGX_ERROR;
}

/* 判断模块是否已经加载 */
for (m = 0; cf->cycle->modules[m]; m++) {
if (ngx_strcmp(cf->cycle->modules[m]->name, module->name) == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"module \"%s\" is already loaded",
module->name);
return NGX_ERROR;
}
}

/*
* if the module wasn't previously loaded, assign an index
*/

/* 模块没有加载的时候 分配一个索引 */
if (module->index == NGX_MODULE_UNSET_INDEX) {
module->index = ngx_module_index(cf->cycle);

/* 当添加该模块后达到最大的模块数量上限的情况 */
if (module->index >= ngx_max_module) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"too many modules loaded");
return NGX_ERROR;
}
}

/*
* put the module into the cycle->modules array
*/

/* 确定模块添加的位置 */

before = cf->cycle->modules_n;

if (order) {
for (i = 0; order[i]; i++) {
if (ngx_strcmp(order[i], module->name) == 0) {
i++;
break;
}
}

for ( /* void */ ; order[i]; i++) {

#if 0
ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0,
"module: %s before %s",
module->name, order[i]);
#endif

for (m = 0; m < before; m++) {
if (ngx_strcmp(cf->cycle->modules[m]->name, order[i]) == 0) {

ngx_log_debug3(NGX_LOG_DEBUG_CORE, cf->log, 0,
"module: %s before %s:%i",
module->name, order[i], m);

before = m;
break;
}
}
}
}

/* put the module before modules[before] */

/* 把before位置以及后面的模块都后移一个单位 modules[before]用来存放添加的module */
if (before != cf->cycle->modules_n) {
ngx_memmove(&cf->cycle->modules[before + 1],
&cf->cycle->modules[before],
(cf->cycle->modules_n - before) * sizeof(ngx_module_t *));
}

cf->cycle->modules[before] = module;
cf->cycle->modules_n++;

/* 当添加的模块是核心模块时 调用该模块的初始化方法 */
if (module->type == NGX_CORE_MODULE) {

/*
* we are smart enough to initialize core modules;
* other modules are expected to be loaded before
* initialization - e.g., http modules must be loaded
* before http{} block
*/

core_module = module->ctx;

if (core_module->create_conf) {
rv = core_module->create_conf(cf->cycle);
if (rv == NULL) {
return NGX_ERROR;
}

cf->cycle->conf_ctx[module->index] = rv;
}
}

return NGX_OK;
}