摘要:在进行Nginx模块开发之前,需要先了解一下Nginx的模块工作原理以及需要用到的结构体。
1、Nginx模块工作原理
当Nginx接到一个HTTP请求时,通过查找配置文件将此次请求映射到一个location块中,而此location中所配置的各个指令则会启动不同的模块去完成工作。通常一个location中的指令会涉及一个handler模块和多个filter模块(当然,多个location可以复用同一个模块)。handler模块负责处理请求,完成响应内容的生成,而filter模块对响应内容进行处理。 在Nginx模块开发中,最重要的三个结构体分别是:ngx_module_t、ngx_http_module_t 和 ngx_command_t。
ngx_module_t:构建nginx由多个ngx_module_t组成,该结构体描述了整个模块的所有信息,为核心模块进行初始化和调用提供了接口 ngx_http_module_t:实现ngx_module_t里面对应的功能 ngx_command_t:使用nginx模块的口令,可以有多个口令
ngx_module_t相当于房间,ngx_http_module_t相当于房间里是用来做什么的,ngx_command_t相当于多种钥匙
2、ngx_module_t 结构体
ngx_module_t 结构体是整个nginx的关键,它提供了整个nginx的模块化的基础,该结构体描述了整个模块的所有信息,为核心模块进行初始化和调用提供了接口。结构体定义及解释如下:
struct ngx_module_s {
......
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);
......
};
3、ngx_command_t 结构体
每个Nginx模块都会定义一个 commands 数组,用于定义和解析 nginx.conf 文件相关参数,每一个数组元素都是 ngx_command_t 类型,数组的结尾用 ngx_null_command 表示。Nginx在解析配置文件中的一个配置项时首先会遍历所有的模块,对于每一个模块而言,通过遍历commands数组进行。
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;
};
各参数含义如下: name: 当nginx.conf里出现了name这个字段就调用这个模块处理。 type: 告诉Nginx这个命令可以出现的位置,例如server或location set: 配置项处理函数,将conf文件里的参数转化成需要的格式并存入配置结构体,可以自己实现,也可以用Nginx内置的14个配置解析函数(后面文章会介绍到) conf:用于指示配置项所处内存的相对偏移位置,仅在type中没有设置NGX_DIRECT_CONF和NGX_MAIN_CONF时才会生效。HTTP模块中可能会定义3个结构体,分别用于存储main、srv、loc级别的配置项(对应于create_main_conf、create_srv_conf、create_loc_conf方法创建的结构体),而HTTP框架自动解析时需要知道应把解析出的配置项值写入哪个结构体中,这将由conf成员完成。 offset:当前配置项在整个存储配置项的结构体中的偏移位置,nginx内部使用 offsetof 计算成员变量在struct中的偏移位置得到。 post:功能由程序员定义
4、ngx_http_module_t
Nginx定义了很多模块,每个模块都有自己的类型,可以定义一些属于自己的操作函数,这里介绍http模块对应的结构体 ngx_http_module_t,结构体定义及解释如下:
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;
5、零散知识
- 5.1 ngx_chain_t 结构体
在向用户发送HTTP 包体时,就要传入ngx_chain_t链表对象。ngx_chain_t 就是一个链表,用来存放完整的响应体,里面的ngx_buf_t 就是存放具体的响应体内容:
struct ngx_chain_s {
ngx_buf_t *buf;
ngx_chain_t *next;
};
其中ngx_buf_t里面改由pos和last变量,分别存放当前节点缓冲区在内存中的起始位置和结束位置,结构示意图如下所示:
- 5.2 srv 和 loc
在Nginx源码中,经常看到函数或宏定义出现srv、SRV、loc、LOC字样,这些分别是server和location的缩写,一般对应nginx.conf里的server段和location段。
下一节:Nginx模块开发系列2–hello_world框架
|