在 ./nginx-1.24.0/src/core/ngx_module.c
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];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 */module->ctx_index = ngx_module_ctx_index(cycle, type, next);if (module->ctx_index > max) {max = module->ctx_index;}next = module->ctx_index + 1;}/** make sure the number returned is big enough for previous* cycle as well, else there will be problems if the number* will be stored in a global variable (as it's used to be)* and we'll have to roll back to the 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 > max) {max = module->ctx_index;}}}/* prevent loading of additional modules */cycle->modules_used = 1;return max + 1;
}
ngx_count_modules
函数的作用是统计 Nginx 中指定类型模块的数量,并为这些模块分配唯一的上下文索引(ctx_index
),最终返回该类型模块的总数
for (i = 0; cycle->modules[i]; i++) {
遍历当前周期(
cycle
)的所有模块
cycle->modules
是一个以NULL
结尾的模块指针数组,存储了当前 Nginx 进程加载的所有模块。
i
从 0 开始递增,直到cycle->modules[i]
为NULL
(即遍历完所有模块)
module = cycle->modules[i];
将当前遍历到的模块指针赋值给变量
module
if (module->type != type) {continue;
}
跳过与目标类型
type
不匹配的模块
if (module->ctx_index != NGX_MODULE_UNSET_INDEX) {
判断当前模块的
ctx_index
是否已被显式分配。
if (module->ctx_index > max) {max = module->ctx_index;
}
记录当前所有模块中的最大索引值
if (module->ctx_index == next) {next++;
}
维护
next
的值,确保新分配的索引是连续的
/* search for some free index */module->ctx_index = ngx_module_ctx_index(cycle, type, next);
调用函数分配索引
为当前模块分配一个未被占用的上下文索引(
ctx_index
)
函数参数 :
cycle
: 当前 Nginx 运行周期,包含模块列表和全局状态。
type
: 模块类型(如NGX_HTTP_MODULE
),确保仅检查同类型模块。
next
: 当前建议的起始索引(从next
开始搜索空闲位置)。函数行为 :
ngx_module_ctx_index
会从next
开始,检查同类型模块是否已占用该索引。如果
next
未被占用,直接返回next
。如果被占用,则递增
next
直到找到未被使用的索引。返回值 :分配的索引值赋给
module->ctx_index
。意义 :
动态分配索引 :确保新模块或未初始化的模块获得唯一索引。
避免冲突 :通过检查现有模块的索引,防止重复。
保持连续性 :尽量从
next
开始分配,使索引尽可能连续(优化内存布局)。
ngx_module_ctx_index
ngx_module_ctx_index-CSDN博客
if (module->ctx_index > max) {max = module->ctx_index;}next = module->ctx_index + 1;
更新 max 和 next
/** make sure the number returned is big enough for previous* cycle as well, else there will be problems if the number* will be stored in a global variable (as it's used to be)* and we'll have to roll back to the 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 > max) {max = module->ctx_index;}}}/* prevent loading of additional modules */cycle->modules_used = 1;return max + 1;
遍历旧周期(
old_cycle
)的模块,确保返回的索引值能覆盖旧模块中的最大索引
cycle->modules_used = 1;
防止后续动态加载新模块,确保模块列表的稳定性
modules_used
是ngx_cycle_t
的标志位,标记模块列表已被使用。一旦标记为
1
,后续调用ngx_add_module
会失败(防止索引被破坏)
return max + 1;
返回
max + 1
,因为索引从 0 开始,总数为最大索引值加一