解剖Nginx·模块开发篇(2)ngx_http_hello_world_module 模块基本结构定义
2014-10-22 16:43
906 查看
elloWorld 是一个典型的 location 模块。什么是 location 模块?在 Nginx 中,根据作用域,有 main 模块、server 模块、location 模块。
在 HelloWorld 例子中:
一般类说会定义很多命令,但是在 HelloWorld 中只有一个命令。
我们一个一个来看。
…
ngx_conf_set_flag_slot:将“on”或者“off”转换成1或0;
ngx_conf_set_str_slot:将字符串保存为ngx_str_t;
ngx_conf_set_num_slot:解析一个数字并保存为ngx_int_t;
ngx_conf_set_size_slot:解析一个数据大小(如:“8k”,“1m”),并保存为size_t;
ngx_conf_set_enum_slot:根据枚举定义将字符串翻译成ngx_int_t;
ngx_http_set_complex_value_slot:解析一个包含nginx变量的字符串并保存为ngx_http_complex_value_t;
这可不是随意指定的,如果你的
最后不要忘了加上 ngx_null_command,以表示命令集合定义完成。
可看到有以下几个部分:
Pre configuration
Post configuration
create main configuration
init main configuration
create server configuration
merge server configuration
create location configuration
merge location configuration
它们都是函数指针,都可以为 NULL,不过我们的模块里用到的是:
这两个函数会在下一篇文章中介绍。
http://blog.sina.com.cn/s/blog_7303a1dc0100x70t.html
-
1 模块定义
在 HelloWorld 模块中有一个 ngx_http_hello_world_module 变量,用于定义模块。它是 ngx_module_t 类型。ngx_module_t 是 ngx_module_s 的别名,其定义如下:struct ngx_module_s { ngx_uint_t ctx_index; ngx_uint_t index; 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; // 命令定义地址 ngx_uint_t type; // 模块类型 ngx_int_t (*init_master)(ngx_log_t *log); // 初始化 master 时执行 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); // 退出 master 时执行 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; };
在 HelloWorld 例子中:
// Structure for the HelloWorld module, the most important thing ngx_module_t ngx_http_hello_world_module = { NGX_MODULE_V1, &ngx_http_hello_world_module_ctx, ngx_http_hello_world_commands, NGX_HTTP_MODULE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NGX_MODULE_V1_PADDING };
1.1 NGX_MODULE_V1
看它的定义你就知道,它是用来填充前 7 个 fields 的。NGX_MODULE_V1 0, 0, 0, 0, 0, 0, 1
1.2 模块类型
我们的模块是 HTTP 模块,还可以开发 CORE 模块,或者 CONF 模块等等。// ngx_http_config.h #define NGX_HTTP_MODULE 0x50545448 /* "HTTP" */ // ngx_conf_file.h #define NGX_CORE_MODULE 0x45524F43 /* "CORE" */ #define NGX_CONF_MODULE 0x464E4F43 /* "CONF" */
1.3 NGX_MODULE_V1_PADDING
这个还是用来填充字段的,或者叫 padding、补白。#define NGX_MODULE_V1_PADDING 0, 0, 0, 0, 0, 0, 0, 0
2 命令定义
命令定义用到如下数据结构: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; };
一般类说会定义很多命令,但是在 HelloWorld 中只有一个命令。
static ngx_command_t ngx_http_hello_world_commands[] = { { ngx_string("hello_world"), // The command name NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1, ngx_http_hello_world, // The command handler NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_hello_world_loc_conf_t, output_words), NULL }, ngx_null_command };
我们一个一个来看。
2.1 命令名称
name 成员表示命令名称2.2 命令类型
type 是命令类型。它可以取如下的一个或多个值的“或”:NGX_HTTP_MAIN_CONF:可出现在 http 的主作用域;
NGX_HTTP_SRV_CONF:可出现在 http 的 server 作用域;
NGX_HTTP_LOC_CONF:可出现在 http 的 location 作用域;
NGX_HTTP_UPS_CONF:可出现在 http 的 upstream 作用域;
NGX_HTTP_SIF_CONF:which will allow the directive to be included in if statements at the server level. [参考]
NGX_CONF_NOARGS:指令没有参数;
NGX_CONF_TAKE1:指令读入1个参数;
NGX_CONF_TAKE2:指令读入2个参数;
…
NGX_CONF_TAKE7:指令读入7个参数;
NGX_CONF_FLAG:指令读入1个布尔型数据(“on”或“off”);
NGX_CONF_1MORE:指令至少读入1个参数;
NGX_CONF_2MORE:指令至少读入2个参数;
// ngx_http_config.h #define NGX_HTTP_MAIN_CONF 0x02000000 #define NGX_HTTP_SRV_CONF 0x04000000 #define NGX_HTTP_LOC_CONF 0x08000000 #define NGX_HTTP_UPS_CONF 0x10000000 #define NGX_HTTP_SIF_CONF 0x20000000 #define NGX_HTTP_LIF_CONF 0x40000000 #define NGX_HTTP_LMT_CONF 0x80000000 // ngx_conf_file.h #define NGX_CONF_NOARGS 0x00000001 #define NGX_CONF_TAKE1 0x00000002 #define NGX_CONF_TAKE2 0x00000004 #define NGX_CONF_TAKE3 0x00000008 #define NGX_CONF_TAKE4 0x00000010 #define NGX_CONF_TAKE5 0x00000020 #define NGX_CONF_TAKE6 0x00000040 #define NGX_CONF_TAKE7 0x00000080 // ngx_conf_file.h #define NGX_CONF_TAKE12 (NGX_CONF_TAKE1|NGX_CONF_TAKE2) #define NGX_CONF_TAKE13 (NGX_CONF_TAKE1|NGX_CONF_TAKE3) #define NGX_CONF_TAKE23 (NGX_CONF_TAKE2|NGX_CONF_TAKE3) #define NGX_CONF_TAKE123 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3) #define NGX_CONF_TAKE1234 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3|NGX_CONF_TAKE4) // ngx_conf_file.h #define NGX_CONF_ARGS_NUMBER 0x000000ff #define NGX_CONF_BLOCK 0x00000100 #define NGX_CONF_FLAG 0x00000200 #define NGX_CONF_ANY 0x00000400 #define NGX_CONF_1MORE 0x00000800 #define NGX_CONF_2MORE 0x00001000 #define NGX_CONF_MULTI 0x00002000
2.3 命令回调函数
这里我们使用的是自己定义的回调函数,还可以使用 Nginx 提供的回调函数,比如:ngx_conf_set_flag_slot:将“on”或者“off”转换成1或0;
ngx_conf_set_str_slot:将字符串保存为ngx_str_t;
ngx_conf_set_num_slot:解析一个数字并保存为ngx_int_t;
ngx_conf_set_size_slot:解析一个数据大小(如:“8k”,“1m”),并保存为size_t;
ngx_conf_set_enum_slot:根据枚举定义将字符串翻译成ngx_int_t;
ngx_http_set_complex_value_slot:解析一个包含nginx变量的字符串并保存为ngx_http_complex_value_t;
2.4 存储位置
conf 参数它有三个可能的取值,分别如下:NGX_HTTP_MAIN_CONF_OFFSET NGX_HTTP_SRV_CONF_OFFSET NGX_HTTP_LOC_CONF_OFFSET
这可不是随意指定的,如果你的
type参数设置了
NGX_HTTP_MAIN_CONF,那么这里就要设置为
NGX_HTTP_MAIN_CONF_OFFSET。相应的,如果是
NGX_HTTP_SRV_CONF或
NGX_HTTP_LOC_CONF,那么这里就要设置为
NGX_HTTP_SRV_CONF_OFFSET和
NGX_HTTP_LOC_CONF_OFFSET。
2.5 offset
表 示数据具体保存在main_conf、srv_conf、loc_conf指向的结构体的哪个位置(offset偏移)。大家可能会问,这个 main_conf等等怎么来的,nginx给我们挖的坑长得是个什么样子,这个我们在介绍 ngx_http_hello_world_module_ctx会说到。2.6 post
一个补充字段,一般不用的,填入NULL。只是对于某些特殊的处理函数,比如ngx_conf_set_enum_slot,会用这个指针来指向enum定义表。最后不要忘了加上 ngx_null_command,以表示命令集合定义完成。
3 上下文定义
用到了 HTTP 模块,定义如下: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;
可看到有以下几个部分:
Pre configuration
Post configuration
create main configuration
init main configuration
create server configuration
merge server configuration
create location configuration
merge location configuration
它们都是函数指针,都可以为 NULL,不过我们的模块里用到的是:
// Structure for the HelloWorld context static ngx_http_module_t ngx_http_hello_world_module_ctx = { NULL, NULL, NULL, NULL, NULL, NULL, ngx_http_hello_world_create_loc_conf, ngx_http_hello_world_merge_loc_conf };
这两个函数会在下一篇文章中介绍。
4 Reference
http://forum.nginx.org/read.php?2,243http://blog.sina.com.cn/s/blog_7303a1dc0100x70t.html
-
相关文章推荐
- 解剖Nginx·模块开发篇(2)ngx_http_hello_world_module 模块基本结构定义
- 解剖Nginx·模块开发篇(2)ngx_http_hello_world_module 模块基本结构定义
- 解剖Nginx·模块开发篇(2)ngx_http_hello_world_module 模块基本结构定义
- 解剖Nginx·模块开发篇(3)ngx_http_hello_world_module 模块的基本函数实现
- 解剖Nginx·模块开发篇(3)ngx_http_hello_world_module 模块的基本函数实现
- 解剖Nginx·模块开发篇(3)ngx_http_hello_world_module 模块的基本函数实现
- 解剖Nginx·模块开发篇(5)解读内置非默认模块 ngx_http_stub_status_module
- 解剖Nginx·模块开发篇(5)解读内置非默认模块 ngx_http_stub_status_module
- 解剖Nginx·模块开发篇(5)解读内置非默认模块 ngx_http_stub_status_module
- 解剖Nginx·模块开发篇(5)解读内置非默认模块 ngx_http_stub_status_module
- Nginx 负载均衡模块 ngx_http_upstream_module 详述
- 解剖Nginx·模块开发篇(4)模块开发中的命名规则和模块加载与运行流程
- ngx_http_core_module模块提供的变量
- 十二.健康检查模块功能(ngx_http_upstream_check_module)
- 解读nginx第三方模块ngx_http_auth_request_module
- 十四.backtrace模块,程序崩溃的时候可以显示出错的调用栈(ngx_http_backtrace_module)
- nginx外部模块编译安装之ngx_http_accesskey_module防盗链
- 详细解释:nginx中ngx_http_auth_basic_module模块(HTTP Auth Basic 模块)配置及各个参数含义 .
- 详细解释:nginx中ngx_http_access_module模块(HTTP Access 模块)配置及各个参数含义
- nginx第三方模块(ngx_http_auth_pam_module)加注释