Nginx学习之路(十)编写一个Nginx的模块-----基本的模块编写步骤

在Nginx上做二次开发大部分时候都是做的模块(module)的开发,今天就来介绍一下Nginx中的module开发的基本步骤,先来认识一下Nginx中的module。

一个基本的module框架(叫框架可能不太准确,这里的意思是需要编写的地方)由以下3个部分组成:

首先是必须要实现的一个command结构体

struct ngx_command_s {    
    ngx_str_t             name;//这个name就是你在需要使用这个module时,在conf文件配置指令的名称    
    ngx_uint_t            type;//type可以是一串指令的并集,它的功能是用来指定这个module应该出现在配置文件中的哪个地方,以及这个配置指令接受几个参数等    
    char              *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);//这个回调函数的功能是当conf文件开始解析这个配置指令时,就会调用这个回调    
    ngx_uint_t conf;//conf字段指定该配置项存储的位置到底在哪个内存池下面,有三个选项NGX_HTTP_MAIN_CONF_OFFSET,NGX_HTTP_SRV_CONF_OFFSET,NGX_HTTP_LOC_CONF_OFFSET    
    ngx_uint_t offset;//offset一般会调用一个offsetof()函数,用于指定配置的指令数据的存放位置距离conf指针偏移值具体为多少   
    void *post;//该字段存储一个指针。可以指向任何一个在读取配置过程中需要的数据,以便于进行配置读取的处理。大多数时候,都不需要,所以简单地设为0即可    
};  

然后需要实现这个module的上下文,上下文的概念可能有点抽象,在这里可以理解成就是注册这个module在Nginx运行的各个阶段需要被调用的相应函数就可以了,上下文的结构体如下:

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);//调用该函数创建本模块位于http block的配置信息存储结构。该函数成功的时候,返回创建的配置对象。失败的话,返回NULL。
    char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);//调用该函数初始化本模块位于http block的配置信息存储结构。该函数成功的时候,返回NGX_CONF_OK。失败的话,返回NGX_CONF_ERROR或错误字符串。

    void       *(*create_srv_conf)(ngx_conf_t *cf);//调用该函数创建本模块位于http server block的配置信息存储结构,每个server block会创建一个。该函数成功的时候,返回创建的配置对象。失败的话,返回NULL。
    char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);//因为有些配置指令既可以出现在http block,也可以出现在http server block中。那么遇到这种情况,每个server都会有自己存储结构来存储该server的配置,但是在这种情况下http block中的配置与server block中的配置信息发生冲突的时候,就需要调用此函数进行合并,该函数并非必须提供,当预计到绝对不会发生需要合并的情况的时候,就无需提供。当然为了安全起见还是建议提供。该函数执行成功的时候,返回NGX_CONF_OK。失败的话,返回NGX_CONF_ERROR或错误字符串。

    void       *(*create_loc_conf)(ngx_conf_t *cf);//调用该函数创建本模块位于location block的配置信息存储结构。每个在配置中指明的location创建一个。该函数执行成功,返回创建的配置对象。失败的话,返回NULL。
    char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);//与merge_srv_conf类似,这个也是进行配置值合并的地方。该函数成功的时候,返回NGX_CONF_OK。失败的话,返回NGX_CONF_ERROR或错误字符串。
} ngx_http_module_t;

这两个部分写好后就是最关键的部分了,需要实现一个module声明的结构体,该结构体如下:

typedef struct ngx_module_s      ngx_module_t;
struct ngx_module_s {
    ngx_uint_t            ctx_index;//后面会根据这个ctx_index来调用前面create_.._conf创建的上下文
    ngx_uint_t            index;
    ngx_uint_t            spare0;
    ngx_uint_t            spare1;
    ngx_uint_t            abi_compatibility;
    ngx_uint_t            major_version;
    ngx_uint_t            minor_version;
    void                 *ctx;
    ngx_command_t        *commands;
    ngx_uint_t            type;
    ngx_int_t           (*init_master)(ngx_log_t *log);//init 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);
    uintptr_t             spare_hook0;//提供一些hook点
    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学习之路(十)编写一个Nginx的模块-----基本的模块编写步骤

人吐槽 人点赞

猜你喜欢

发表评论

用户名: 密码:
验证码: 匿名发表

你可以使用这些语言

查看评论:Nginx学习之路(十)编写一个Nginx的模块-----基本的模块编写步骤