Nginx源码分析 - 主流程篇 - 模块的初始化(12)
目录
一、模块的数据结构
1. ngx_module_s 模块结构
2. ngx_core_module 核心模块
二、模块的初始化
1. 模块编号处理ngx_preinit_modules
2. 初始化cycle->modules 分配内存
3. 每个模块进行初始化ngx_init_modules
4. 统计有多少个模块ngx_count_modules
5. 模块的工作进程初始化init_process
Nginx是高度模块化的,各个功能都会封装在模块中。例如core模块、HTTP模块等。也可以自定义模块。
这一篇文章主要讲解模块的初始化。后续会有一篇文章教你如何编写Nginx的模块。
Nginx实现模块管理的代码主要在:/src/core/ngx_module.c文件中。
一、模块的数据结构
1. ngx_module_s 模块结构
结构体ngx_module_s主要用于管理每一个模块的详细信息。
Nginx的所有模块会放置在全局变量cycle的cycle->modules 模块数组。通过这个数组,我们就可以拿到每个模块的具体信息。
/*** 业务模块数据结构*/
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;
};
说明:
1. index 主要用于模块的标识。
cycle->conf_ctx主要存储的是各个模块的配置文件结构的指针地址。
cycle->conf_ctx中获取各个模块配置信息都是通过模块的标识来确定数组位置的。
例如核心模块是放在一个ngx_core_conf_t的数据结构上的。而ngx_core_conf_t这个指针就通过index索引值放在cycle->conf_ctx数组中。
获取核心模块的配置信息:
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
2. commands主要用于配置模块的命令集。Nginx的配置文件都是通过commands命令集来逐个解析具体定义好的配置信息(每个模块不一样)。下一章会详解解读
3. ctx 模块上下文。主要放置一个模块自定义的结构。例如核心模块就是ngx_core_module_t的结构。ngx_core_module_t中可以自定义一些方法或者参数。
4. type。模块类型。
5. init_module:初始化模块的时候会回调的函数。
2. ngx_core_module 核心模块
核心模块在nginx.c的头部就定义了。定义了 ngx_core_module核心模块和核心模块的上下文ngx_core_module_ctx
ngx_core_module_t 为核心模块的上下文结构。主要用于核心模块的配置文件创建ngx_core_module_create_conf和初始化ngx_core_module_init_conf。放置在ngx_module_s->ctx。
/*** 核心模块core数据结构* ngx_module_s->ctx 核心模块的上下文,主要定义了创建配置和初始化配置的结构*/
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_core_module_create_conf 核心模块创建配置文件* ngx_core_module_init_conf 核心模块初始化配置文件*/
static ngx_core_module_t ngx_core_module_ctx = {ngx_string("core"),ngx_core_module_create_conf,ngx_core_module_init_conf
};/*** 核心模块*/
ngx_module_t ngx_core_module = {NGX_MODULE_V1,&ngx_core_module_ctx, /* module context */ngx_core_commands, /* module directives */NGX_CORE_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. 模块编号处理ngx_preinit_modules
在nginx.c的main函数中,第一步对模块的处理就是进行编号处理。仅仅是编号,不做任何其他处理。
nginx.c:
/* 初始化所有模块;并对所有模块进行编号处理;* ngx_modules数却是在自动编译的时候生成的,位于objs/ngx_modules.c文件中 */if (ngx_preinit_modules() != NGX_OK) {return 1;}
ngx_module.c 具体函数实现
/*** 初始化所有模块;并对所有模块进行编号处理;*/
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_modules的数组得到的。
ngx_modules是一个引用外部的变量。在ngx_modules.h中
/* 模块数组,所有的模块都会保存在此数组中 共有四种类型模块:"CORE","CONF","EVNT","HTTP" */
extern ngx_module_t *ngx_modules[];
而ngx_modules的模块到底是什么时候确定的呢?
具体的模块可通过编译前的configure命令进行配置,即设置哪些模块需要编译,哪些不被编译。当编译的时候,会生成ngx_modules.c的文件,里面就包含模块数组。
新增模块或者减少模块可以在configure命令执行前 auto/modules文件里面修改。
生成的objs/ngx_modules.c文件如下:
00001:
00002: #include <ngx_config.h>
00003: #include <ngx_core.h>
00004:
00005:
00006:
00007: extern ngx_module_t ngx_core_module;
00008: extern ngx_module_t ngx_errlog_module;
00009: extern ngx_module_t ngx_conf_module;
00010: extern ngx_module_t ngx_events_module;
00011: extern ngx_module_t ngx_event_core_module;
00012: extern ngx_module_t ngx_epoll_module;
00013: extern ngx_module_t ngx_http_module;
00014: extern ngx_module_t ngx_http_core_module;
00015: extern ngx_module_t ngx_http_log_module;
00016: extern ngx_module_t ngx_http_upstream_module;
00017: extern ngx_module_t ngx_http_static_module;
00018: extern ngx_module_t ngx_http_autoindex_module;
00019: extern ngx_module_t ngx_http_index_module;
00020: extern ngx_module_t ngx_http_auth_basic_module;
00021: extern ngx_module_t ngx_http_access_module;
00022: extern ngx_module_t ngx_http_limit_zone_module;
00023: extern ngx_module_t ngx_http_limit_req_module;
00024: extern ngx_module_t ngx_http_geo_module;
00025: extern ngx_module_t ngx_http_map_module;
00026: extern ngx_module_t ngx_http_split_clients_module;
00027: extern ngx_module_t ngx_http_referer_module;
00028: extern ngx_module_t ngx_http_rewrite_module;
00029: extern ngx_module_t ngx_http_proxy_module;
00030: extern ngx_module_t ngx_http_fastcgi_module;
00031: extern ngx_module_t ngx_http_uwsgi_module;
00032: extern ngx_module_t ngx_http_scgi_module;
00033: extern ngx_module_t ngx_http_memcached_module;
00034: extern ngx_module_t ngx_http_empty_gif_module;
00035: extern ngx_module_t ngx_http_browser_module;
00036: extern ngx_module_t ngx_http_upstream_ip_hash_module;
00037: extern ngx_module_t ngx_http_stub_status_module;
00038: extern ngx_module_t ngx_http_write_filter_module;
00039: extern ngx_module_t ngx_http_header_filter_module;
00040: extern ngx_module_t ngx_http_chunked_filter_module;
00041: extern ngx_module_t ngx_http_range_header_filter_module;
00042: extern ngx_module_t ngx_http_gzip_filter_module;
00043: extern ngx_module_t ngx_http_postpone_filter_module;
00044: extern ngx_module_t ngx_http_ssi_filter_module;
00045: extern ngx_module_t ngx_http_charset_filter_module;
00046: extern ngx_module_t ngx_http_userid_filter_module;
00047: extern ngx_module_t ngx_http_headers_filter_module;
00048: extern ngx_module_t ngx_http_copy_filter_module;
00049: extern ngx_module_t ngx_http_range_body_filter_module;
00050: extern ngx_module_t ngx_http_not_modified_filter_module;
00051:
2. 初始化cycle->modules 分配内存
主要在cycle->modules上分配一块用于存放ngx_module_s数据结构的列表内存。并且将原来的 ngx_modules拷贝到cycle->modules上。
ngx_cycle.c
/* 创建模块以及创建模块的配置信息 */if (ngx_cycle_modules(cycle) != NGX_OK) {ngx_destroy_pool(pool);return NULL;}
ngx_modules.c
/*** ngx_init_cycle 在初始化cycle的时候,初始化模块* 创建一个列表,并将静态的模块拷贝到列表上*/
ngx_int_t
ngx_cycle_modules(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;
}
3. 每个模块进行初始化ngx_init_modules
ngx_module_s结构中定义了init_module的模块初始化回调函数。ngx_init_modules主要用于每个模块的初始化工作。
在编写自定义模块的时候,可以定义init_module方法,主要用于这个模块的初始化工作。
ngx_cycle.c
/* 调用每个模块的初始化函数 */if (ngx_init_modules(cycle) != NGX_OK) {/* fatal */exit(1);}
真正的各个模块初始化 ngx_modules.c:
/*** 对每个模块进行一次初始化操作* 调用 init_module 回调函数,初始化每个模块的数据*/
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;
}
4. 统计有多少个模块ngx_count_modules
/*** 统计每个类型下面总共多少个模块*/
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;
}
5. 模块的工作进程初始化init_process
在nginx_process_cycle.c文件的ngx_worker_process_init方法(Nginx是多进程模式的,此方法是每个进程进行自己的初始化工作)中包含模块的进程初始化。
模块进程初始化,主要回调模块数据结构中的init_process回调函数。
此方法,会在后面的章节中详细讲解。
/* 对模块进程初始化 - 这边初始化的是所有的模块有init_process回调函数的进行初始化工作 */for (i = 0; cycle->modules[i]; i++) {if (cycle->modules[i]->init_process) {if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {/* fatal */exit(2);}}}
Nginx源码分析 - 主流程篇 - 模块的初始化(12)相关推荐
- Python3.5源码分析-内建模块builtins初始化
Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3模块初始化与加载 Python的模块分为内建的模 ...
- Nginx源码分析:核心模块剖析及常见问题
Nginx 在解析完请求行和请求头之后,一共定义了十一个阶段,分别介绍如下 HTTP 模块工作原理 HTTP 处理的十一个阶段定义 typedef enum { NGX_HTTP_POST_READ_ ...
- Nginx 源码分析
1.工程 ngx_conf_file.c ngx_connection.c ngx_cycle.c ngx_file.h ngx_module.c ngx_open_file_cache.h ngx_ ...
- Lua源码分析 - 虚拟机篇 - 语义解析之Opcode执行(18)
目录 一.虚拟机篇 - 指令执行状态机luaV_execute 二.虚拟机篇 - 状态机的具体实现原理 一.虚拟机篇 - 指令执行状态机luaV_execute 在<Lua源码分析 - 主流程篇 ...
- Nginx源码分析:epoll事件处理模块概述
nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 事件处理模块概述 Nginx的高效请求的处理依赖于事件管理机制,本次默认的场景是Linux操 ...
- Nginx 源码分析-- 模块module 解析执行 nginx.conf 配置文件流程分析 一
搭建nginx服务器时,主要的配置文件 nginx.conf 是部署和维护服务器人员经常要使用到的文件, 里面进行了许多服务器参数的设置.那么nginx 以模块 module为骨架的设计下是如何运用模 ...
- nginx源码分析(5)——监听socket初始化
在nginx源码分析(4)中,看到了nginx的事件模型,但其中没有介绍监听socket的初始化.而对于web server来说,需要通过监听socket来监听客户端的连接等.本篇将会具体介绍这方面的 ...
- nginx源码分析之网络初始化
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...
- Nginx源码分析:惊群处理与负载均衡
nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> Nginx的惊群处理与负载均衡概述 当Nginx工作在master/worker模式下时,就 ...
- Nginx源码分析:核心数据结构ngx_cycle_t与内存池概述
nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 核心数据结构与内存池概述 在Nginx中的核心数据结构就是ngx_cycle_t结构,在初始 ...
最新文章
- 时间序列python复杂网络实例_基于时间序列数据的复杂网络重构
- 队列服务 php,php Redis 队列服务的简单示例
- 会计基础第二次模拟试题(1)
- 预训练再次跨界!百度提出ERNIE-GeoL,地理位置-语言联合预训练!
- linux erlang安装教程,linux(CentOS7)中安装erlang(20.3)以及rabbitmq(3.6.15)的步骤以及一些注意事项...
- java 6 损坏,Java 异常处理六
- Python 数据结构与算法——图(Graph)
- SpringBoot使用AutoConfiguration自定义Starter
- 解读 JVM 类加载器-一篇文章简单易懂
- 骨架屏Skeleton Screen
- proto_path passed empty directory name. (Use “.“ for current directory.)
- smb.php如何使用,win10smb1协议怎么开
- iOS关于图片点到像素转换之杂谈
- [工作积累] TAA Ghosting 的相关问题
- MAC电脑配置maven
- 智联招聘让人非常反感的一个功能:自动委托投递!
- 平面设计师资格证怎么考
- Google 重申对 Kotlin 编程语言 Android 的承诺:谷歌推出 Kotlin 免费在线课程 Kotlin Bootcamp Course 2
- 用计算机播放vcd教案,六年级信息技术下册 第六课制作班级VCD1教案 华中师大版...
- 美国考试能用计算机吗,2020年美国cpa考试允许考生自带计算器吗?