解剖Nginx·模組開發篇(2)ngx_http_hello_world_module 模組基本結構定義
解剖Nginx·模組開發篇(2)ngx_http_hello_world_module 基本結構定義
- 作者:柳大·Poechant(鍾超)
- 郵箱:zhongchao.ustc#gmail.com(# -> @)
- 部落格:Blog.CSDN.net/Poechant
- 日期:June 2nd, 2012
HelloWorld 是一個典型的 location 模組。什麼是 location 模組?在 Nginx 中,根據作用域,有 main 模組、server 模組、location 模組。
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,243
- http://blog.sina.com.cn/s/blog_7303a1dc0100x70t.html
-
轉載請註明來自柳大的CSDN部落格:Blog.CSDN.net/Poechant
-
相關文章
- 解剖Nginx·模組開發篇(3)ngx_http_hello_world_module 模組的基本函式實現NginxHTTP函式
- 解剖Nginx·模組開發篇(1)跑起你的 Hello World 模組!Nginx
- 解剖Nginx·模組開發篇(4)模組開發中的命名規則和模組載入與執行流程Nginx
- 解剖Nginx·模組開發篇(6)配置檔案config入門Nginx
- 解剖Nginx·模組開發篇(5)解讀內建非預設模組 ngx_http_stub_status_moduleNginxHTTP
- nginx模組開發Nginx
- 深入理解Nginx:模組開發與架構解析(第2版)Nginx架構
- 介面模組的定義
- nginx事件模組 -- 第二篇Nginx事件
- nginx事件模組-- 第四篇Nginx事件
- nginx事件模組 -- 第三篇Nginx事件
- CMD 模組定義規範
- nginx事件模組 -- 第一篇Nginx事件
- 解剖Nginx·自動指令碼篇(2)設定初始變數指令碼 auto/initNginx指令碼變數
- 評論模組開發總結
- 上傳模組開發總結
- 程式模組化設計結構化開發優勢
- nginx學習筆記(2):開發一個簡單的HTTP模組Nginx筆記HTTP
- Nginx 架構——【核心流程+模組介紹】Nginx架構
- Nginx的Uwsgi模組(部分模組指令)Nginx
- NGINX模組(一)Nginx
- NGINX模組(二)Nginx
- Android 開發功能模組總結Android
- Nginx limit模組限制併發數NginxMIT
- Zepto自定義模組打包構建
- Nginx 學習總結(4)—— Rewrite 模組Nginx
- Nginx通過geo模組設定白名單Nginx
- 二、FFmpeg的模組結構
- rust 模組組織結構Rust
- 設計與實現模組管理系統基本功能定義自己(18--設計模組附件[1])
- nginx事件模組 -- 第五篇 epoll addNginx事件
- Nginx 新增 lua 模組Nginx
- 為 Nginx 新增模組Nginx
- Nginx常用的模組Nginx
- Nginx的Uwsgi模組Nginx
- 使用typescript開發angular模組(編寫模組)TypeScriptAngular
- JavaScript 模組(2):模組打包JavaScript
- Nginx利用ngx_http_upstream_module模組定義後端伺服器組NginxHTTP後端伺服器