在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Linux/ 模塊的基本結(jié)構(gòu)
示例: hello handler 模塊
什么是 Nginx
handler 模塊的掛載
Nginx 特點(diǎn)
handler 模塊簡(jiǎn)介
初探 Nginx 架構(gòu)
Nginx 的模塊化體系結(jié)構(gòu)
更多 handler 模塊示例分析
Nginx 基礎(chǔ)概念
upstream 模塊簡(jiǎn)介
Nginx 的請(qǐng)求處理
過(guò)濾模塊簡(jiǎn)介
基本數(shù)據(jù)結(jié)構(gòu)
模塊的基本結(jié)構(gòu)
負(fù)載均衡模塊
過(guò)濾模塊的分析
core 模塊
handler 模塊的基本結(jié)構(gòu)
Nginx 的配置系統(tǒng)
handler 的編寫(xiě)步驟
handler 模塊的編譯和使用
event 模塊

模塊的基本結(jié)構(gòu)

在這一節(jié)我們將會(huì)對(duì)通常的模塊開(kāi)發(fā)過(guò)程中,每個(gè)模塊所包含的一些常用的部分進(jìn)行說(shuō)明。這些部分有些是必須的,有些不是必須的。同時(shí)這里所列出的這些東西對(duì)于其他類(lèi)型的模塊,例如 filter 模塊等也都是相同的。

模塊配置結(jié)構(gòu)

基本上每個(gè)模塊都會(huì)提供一些配置指令,以便于用戶(hù)可以通過(guò)配置來(lái)控制該模塊的行為。那么這些配置信息怎么存儲(chǔ)呢?那就需要定義該模塊的配置結(jié)構(gòu)來(lái)進(jìn)行存儲(chǔ)。

大家都知道 Nginx 的配置信息分成了幾個(gè)作用域(scope,有時(shí)也稱(chēng)作上下文),這就是 main,server 以及 location。同樣的每個(gè)模塊提供的配置指令也可以出現(xiàn)在這幾個(gè)作用域里。那對(duì)于這三個(gè)作用域的配置信息,每個(gè)模塊就需要定義三個(gè)不同的數(shù)據(jù)結(jié)構(gòu)去進(jìn)行存儲(chǔ)。當(dāng)然,不是每個(gè)模塊都會(huì)在這三個(gè)作用域都提供配置指令的。那么也就不一定每個(gè)模塊都需要定義三個(gè)數(shù)據(jù)結(jié)構(gòu)去存儲(chǔ)這些配置信息了。視模塊的實(shí)現(xiàn)而言,需要幾個(gè)就定義幾個(gè)。

有一點(diǎn)需要特別注意的就是,在模塊的開(kāi)發(fā)過(guò)程中,我們最好使用 Nginx 原有的命名習(xí)慣。這樣跟原代碼的契合度更高,看起來(lái)也更舒服。

對(duì)于模塊配置信息的定義,命名習(xí)慣是ngx_http_<module name>_(main|srv|loc)_conf_t。這里有個(gè)例子,就是從我們后面將要展示給大家的 hello module 中截取的。

    typedef struct
    {
        ngx_str_t hello_string;
        ngx_int_t hello_counter;
    }ngx_http_hello_loc_conf_t;

模塊配置指令

一個(gè)模塊的配置指令是定義在一個(gè)靜態(tài)數(shù)組中的。同樣地,我們來(lái)看一下從 hello module 中截取的模塊配置指令的定義。

    static ngx_command_t ngx_http_hello_commands[] = {
       { 
            ngx_string("hello_string"),
            NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,
            ngx_http_hello_string,
            NGX_HTTP_LOC_CONF_OFFSET,
            offsetof(ngx_http_hello_loc_conf_t, hello_string),
            NULL },

        { 
            ngx_string("hello_counter"),
            NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
            ngx_http_hello_counter,
            NGX_HTTP_LOC_CONF_OFFSET,
            offsetof(ngx_http_hello_loc_conf_t, hello_counter),
            NULL },               

        ngx_null_command
    };

其實(shí)看這個(gè)定義,就基本能看出來(lái)一些信息。例如,我們是定義了兩個(gè)配置指令,一個(gè)是叫 hello_string,可以接受一個(gè)參數(shù),或者是沒(méi)有參數(shù)。另外一個(gè)命令是 hello_counter,接受一個(gè) NGX_CONF_FLAG 類(lèi)型的參數(shù)。除此之外,似乎看起來(lái)有點(diǎn)迷惑。沒(méi)有關(guān)系,我們來(lái)詳細(xì)看一下 ngx_command_t,一旦我們了解這個(gè)結(jié)構(gòu)的詳細(xì)信息,那么我相信上述這個(gè)定義所表達(dá)的所有信息就不言自明了。

ngx_command_t 的定義,位于src/core/ngx_conf_file.h中。

    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: 配置指令的名稱(chēng)。

type: 該配置的類(lèi)型,其實(shí)更準(zhǔn)確一點(diǎn)說(shuō),是該配置指令屬性的集合。Nginx 提供了很多預(yù)定義的屬性值(一些宏定義),通過(guò)邏輯或運(yùn)算符可組合在一起,形成對(duì)這個(gè)配置指令的詳細(xì)的說(shuō)明。下面列出可在這里使用的預(yù)定義屬性值及說(shuō)明。

  • NGX_CONF_NOARGS:配置指令不接受任何參數(shù)。
  • NGX_CONF_TAKE1:配置指令接受 1 個(gè)參數(shù)。
  • NGX_CONF_TAKE2:配置指令接受 2 個(gè)參數(shù)。
  • NGX_CONF_TAKE3:配置指令接受 3 個(gè)參數(shù)。
  • NGX_CONF_TAKE4:配置指令接受 4 個(gè)參數(shù)。
  • NGX_CONF_TAKE5:配置指令接受 5 個(gè)參數(shù)。
  • NGX_CONF_TAKE6:配置指令接受 6 個(gè)參數(shù)。
  • NGX_CONF_TAKE7:配置指令接受 7 個(gè)參數(shù)。

可以組合多個(gè)屬性,比如一個(gè)指令即可以不填參數(shù),也可以接受1個(gè)或者2個(gè)參數(shù)。那么就是NGX_CONF_NOARGS|NGX_CONF_TAKE1|NGX_CONF_TAKE2。如果寫(xiě)上面三個(gè)屬性在一起,你覺(jué)得麻煩,那么沒(méi)有關(guān)系,Nginx 提供了一些定義,使用起來(lái)更簡(jiǎn)潔。

  • NGX_CONF_TAKE12:配置指令接受 1 個(gè)或者 2 個(gè)參數(shù)。
  • NGX_CONF_TAKE13:配置指令接受 1 個(gè)或者 3 個(gè)參數(shù)。
  • NGX_CONF_TAKE23:配置指令接受 2 個(gè)或者 3 個(gè)參數(shù)。
  • NGX_CONF_TAKE123:配置指令接受 1 個(gè)或者 2 個(gè)或者 3 參數(shù)。
  • NGX_CONF_TAKE1234:配置指令接受 1 個(gè)或者 2 個(gè)或者 3 個(gè)或者 4 個(gè)參數(shù)。
  • NGX_CONF_1MORE:配置指令接受至少一個(gè)參數(shù)。
  • NGX_CONF_2MORE:配置指令接受至少兩個(gè)參數(shù)。
  • NGX_CONF_MULTI: 配置指令可以接受多個(gè)參數(shù),即個(gè)數(shù)不定。
  • NGX_CONF_BLOCK:配置指令可以接受的值是一個(gè)配置信息塊。也就是一對(duì)大括號(hào)括起來(lái)的內(nèi)容。里面可以再包括很多的配置指令。比如常見(jiàn)的 server 指令就是這個(gè)屬性的。
  • NGX_CONF_FLAG:配置指令可以接受的值是"on"或者"off",最終會(huì)被轉(zhuǎn)成 bool 值。
  • NGX_CONF_ANY:配置指令可以接受的任意的參數(shù)值。一個(gè)或者多個(gè),或者"on"或者"off",或者是配置塊。

最后要說(shuō)明的是,無(wú)論如何,Nginx 的配置指令的參數(shù)個(gè)數(shù)不可以超過(guò) NGX_CONF_MAX_ARGS 個(gè)。目前這個(gè)值被定義為 8,也就是不能超過(guò) 8 個(gè)參數(shù)值。

下面介紹一組說(shuō)明配置指令可以出現(xiàn)的位置的屬性。

  • NGX_DIRECT_CONF:可以出現(xiàn)在配置文件中最外層。例如已經(jīng)提供的配置指令 daemon,master_process 等。
  • NGX_MAIN_CONF: http、mail、events、error_log 等。
  • NGX_ANY_CONF: 該配置指令可以出現(xiàn)在任意配置級(jí)別上。

對(duì)于我們編寫(xiě)的大多數(shù)模塊而言,都是在處理http相關(guān)的事情,也就是所謂的都是NGX_HTTP_MODULE,對(duì)于這樣類(lèi)型的模塊,其配置可能出現(xiàn)的位置也是分為直接出現(xiàn)在http里面,以及其他位置。

  • NGX_HTTP_MAIN_CONF: 可以直接出現(xiàn)在 http 配置指令里。
  • NGX_HTTP_SRV_CONF: 可以出現(xiàn)在 http 里面的 server 配置指令里。
  • NGX_HTTP_LOC_CONF: 可以出現(xiàn)在 http server 塊里面的 location 配置指令里。
  • NGX_HTTP_UPS_CONF: 可以出現(xiàn)在 http 里面的 upstream 配置指令里。
  • NGX_HTTP_SIF_CONF: 可以出現(xiàn)在 http 里面的 server 配置指令里的 if 語(yǔ)句所在的 block 中。
  • NGX_HTTP_LMT_CONF: 可以出現(xiàn)在 http 里面的 limit_except 指令的 block 中。
  • NGX_HTTP_LIF_CONF: 可以出現(xiàn)在 http server 塊里面的 location 配置指令里的 if 語(yǔ)句所在的 block 中。

set: 這是一個(gè)函數(shù)指針,當(dāng) Nginx 在解析配置的時(shí)候,如果遇到這個(gè)配置指令,將會(huì)把讀取到的值傳遞給這個(gè)函數(shù)進(jìn)行分解處理。因?yàn)榫唧w每個(gè)配置指令的值如何處理,只有定義這個(gè)配置指令的人是最清楚的。來(lái)看一下這個(gè)函數(shù)指針要求的函數(shù)原型。

char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

先看該函數(shù)的返回值,處理成功時(shí),返回 NGX_OK,否則返回 NGX_CONF_ERROR 或者是一個(gè)自定義的錯(cuò)誤信息的字符串。

再看一下這個(gè)函數(shù)被調(diào)用的時(shí)候,傳入的三個(gè)參數(shù)。

  • cf: 該參數(shù)里面保存從配置文件讀取到的原始字符串以及相關(guān)的一些信息。特別注意的是這個(gè)參數(shù)的args字段是一個(gè) ngx_str_t類(lèi)型的數(shù)組,該數(shù)組的首個(gè)元素是這個(gè)配置指令本身,第二個(gè)元素是指令的第一個(gè)參數(shù),第三個(gè)元素是第二個(gè)參數(shù),依次類(lèi)推。

  • cmd: 這個(gè)配置指令對(duì)應(yīng)的 ngx_command_t 結(jié)構(gòu)。

  • conf: 就是定義的存儲(chǔ)這個(gè)配置值的結(jié)構(gòu)體,比如在上面展示的那個(gè) ngx_http_hello_loc_conf_t。當(dāng)解析這個(gè) hello_string 變量的時(shí)候,傳入的 conf 就指向一個(gè) ngx_http_hello_loc_conf_t 類(lèi)型的變量。用戶(hù)在處理的時(shí)候可以使用類(lèi)型轉(zhuǎn)換,轉(zhuǎn)換成自己知道的類(lèi)型,再進(jìn)行字段的賦值。

為了更加方便的實(shí)現(xiàn)對(duì)配置指令參數(shù)的讀取,Nginx 已經(jīng)默認(rèn)提供了對(duì)一些標(biāo)準(zhǔn)類(lèi)型的參數(shù)進(jìn)行讀取的函數(shù),可以直接賦值給 set 字段使用。下面來(lái)看一下這些已經(jīng)實(shí)現(xiàn)的 set 類(lèi)型函數(shù)。

  • ngx_conf_set_flag_slot: 讀取 NGX_CONF_FLAG 類(lèi)型的參數(shù)。
  • ngx_conf_set_str_slot:讀取字符串類(lèi)型的參數(shù)。
  • ngx_conf_set_str_array_slot: 讀取字符串?dāng)?shù)組類(lèi)型的參數(shù)。
  • ngx_conf_set_keyval_slot: 讀取鍵值對(duì)類(lèi)型的參數(shù)。
  • ngx_conf_set_num_slot: 讀取整數(shù)類(lèi)型(有符號(hào)整數(shù) ngx_int_t)的參數(shù)。
  • ngx_conf_set_size_slot:讀取 size_t 類(lèi)型的參數(shù),也就是無(wú)符號(hào)數(shù)。
  • ngx_conf_set_off_slot: 讀取 off_t 類(lèi)型的參數(shù)。
  • ngx_conf_set_msec_slot: 讀取毫秒值類(lèi)型的參數(shù)。
  • ngx_conf_set_sec_slot: 讀取秒值類(lèi)型的參數(shù)。
  • ngx_conf_set_bufs_slot: 讀取的參數(shù)值是 2 個(gè),一個(gè)是 buf 的個(gè)數(shù),一個(gè)是 buf 的大小。例如: output_buffers 1 128k;
  • ngx_conf_set_enum_slot: 讀取枚舉類(lèi)型的參數(shù),將其轉(zhuǎn)換成整數(shù) ngx_uint_t 類(lèi)型。
  • ngx_conf_set_bitmask_slot: 讀取參數(shù)的值,并將這些參數(shù)的值以 bit 位的形式存儲(chǔ)。例如:HttpDavModule 模塊的 dav_methods 指令。

conf: 該字段被 NGX_HTTP_MODULE 類(lèi)型模塊所用 (我們編寫(xiě)的基本上都是 NGX_HTTP_MOUDLE,只有一些 Nginx 核心模塊是非 NGX_HTTP_MODULE),該字段指定當(dāng)前配置項(xiàng)存儲(chǔ)的內(nèi)存位置。實(shí)際上是使用哪個(gè)內(nèi)存池的問(wèn)題。因?yàn)?http 模塊對(duì)所有 http 模塊所要保存的配置信息,劃分了 main, server 和 location 三個(gè)地方進(jìn)行存儲(chǔ),每個(gè)地方都有一個(gè)內(nèi)存池用來(lái)分配存儲(chǔ)這些信息的內(nèi)存。這里可能的值為 NGX_HTTP_MAIN_CONF_OFFSET、NGX_HTTP_SRV_CONF_OFFSET 或 NGX_HTTP_LOC_CONF_OFFSET。當(dāng)然也可以直接置為 0,就是 NGX_HTTP_MAIN_CONF_OFFSET。

offset: 指定該配置項(xiàng)值的精確存放位置,一般指定為某一個(gè)結(jié)構(gòu)體變量的字段偏移。因?yàn)閷?duì)于配置信息的存儲(chǔ),一般我們都是定義個(gè)結(jié)構(gòu)體來(lái)存儲(chǔ)的。那么比如我們定義了一個(gè)結(jié)構(gòu)體 A,該項(xiàng)配置的值需要存儲(chǔ)到該結(jié)構(gòu)體的 b 字段。那么在這里就可以填寫(xiě)為 offsetof(A, b)。對(duì)于有些配置項(xiàng),它的值不需要保存或者是需要保存到更為復(fù)雜的結(jié)構(gòu)中時(shí),這里可以設(shè)置為 0。

post: 該字段存儲(chǔ)一個(gè)指針??梢灾赶蛉魏我粋€(gè)在讀取配置過(guò)程中需要的數(shù)據(jù),以便于進(jìn)行配置讀取的處理。大多數(shù)時(shí)候,都不需要,所以簡(jiǎn)單地設(shè)為 0 即可。

看到這里,應(yīng)該就比較清楚了。ngx_http_hello_commands 這個(gè)數(shù)組每 5 個(gè)元素為一組,用來(lái)描述一個(gè)配置項(xiàng)的所有情況。那么如果有多個(gè)配置項(xiàng),只要按照需要再增加 5 個(gè)對(duì)應(yīng)的元素對(duì)新的配置項(xiàng)進(jìn)行說(shuō)明。

需要注意的是,就是在ngx_http_hello_commands這個(gè)數(shù)組定義的最后,都要加一個(gè)ngx_null_command作為結(jié)尾。

模塊上下文結(jié)構(gòu)

這是一個(gè) ngx_http_module_t 類(lèi)型的靜態(tài)變量。這個(gè)變量實(shí)際上是提供一組回調(diào)函數(shù)指針,這些函數(shù)有在創(chuàng)建存儲(chǔ)配置信息的對(duì)象的函數(shù),也有在創(chuàng)建前和創(chuàng)建后會(huì)調(diào)用的函數(shù)。這些函數(shù)都將被 Nginx 在合適的時(shí)間進(jìn)行調(diào)用。

    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; 
  • preconfiguration: 在創(chuàng)建和讀取該模塊的配置信息之前被調(diào)用。

  • postconfiguration: 在創(chuàng)建和讀取該模塊的配置信息之后被調(diào)用。

  • create_main_conf: 調(diào)用該函數(shù)創(chuàng)建本模塊位于 http block 的配置信息存儲(chǔ)結(jié)構(gòu)。該函數(shù)成功的時(shí)候,返回創(chuàng)建的配置對(duì)象。失敗的話(huà),返回 NULL。

  • init_main_conf: 調(diào)用該函數(shù)初始化本模塊位于 http block 的配置信息存儲(chǔ)結(jié)構(gòu)。該函數(shù)成功的時(shí)候,返回 NGX_CONF_OK。失敗的話(huà),返回 NGX_CONF_ERROR 或錯(cuò)誤字符串。

  • create_srv_conf: 調(diào)用該函數(shù)創(chuàng)建本模塊位于 http server block 的配置信息存儲(chǔ)結(jié)構(gòu),每個(gè) server block 會(huì)創(chuàng)建一個(gè)。該函數(shù)成功的時(shí)候,返回創(chuàng)建的配置對(duì)象。失敗的話(huà),返回 NULL。

  • merge_srv_conf: 因?yàn)橛行┡渲弥噶罴瓤梢猿霈F(xiàn)在 http block,也可以出現(xiàn)在 http server block 中。那么遇到這種情況,每個(gè) server 都會(huì)有自己存儲(chǔ)結(jié)構(gòu)來(lái)存儲(chǔ)該 server 的配置,但是在這種情況下 http block 中的配置與 server block 中的配置信息發(fā)生沖突的時(shí)候,就需要調(diào)用此函數(shù)進(jìn)行合并,該函數(shù)并非必須提供,當(dāng)預(yù)計(jì)到絕對(duì)不會(huì)發(fā)生需要合并的情況的時(shí)候,就無(wú)需提供。當(dāng)然為了安全起見(jiàn)還是建議提供。該函數(shù)執(zhí)行成功的時(shí)候,返回 NGX_CONF_OK。失敗的話(huà),返回 NGX_CONF_ERROR 或錯(cuò)誤字符串。

  • create_loc_conf: 調(diào)用該函數(shù)創(chuàng)建本模塊位于 location block 的配置信息存儲(chǔ)結(jié)構(gòu)。每個(gè)在配置中指明的 location 創(chuàng)建一個(gè)。該函數(shù)執(zhí)行成功,返回創(chuàng)建的配置對(duì)象。失敗的話(huà),返回 NULL。

  • merge_loc_conf: 與 merge_srv_conf 類(lèi)似,這個(gè)也是進(jìn)行配置值合并的地方。該函數(shù)成功的時(shí)候,返回 NGX_CONF_OK。失敗的話(huà),返回 NGX_CONF_ERROR 或錯(cuò)誤字符串。

Nginx 里面的配置信息都是上下一層層的嵌套的,對(duì)于具體某個(gè) location 的話(huà),對(duì)于同一個(gè)配置,如果當(dāng)前層次沒(méi)有定義,那么就使用上層的配置,否則使用當(dāng)前層次的配置。

這些配置信息一般默認(rèn)都應(yīng)該設(shè)為一個(gè)未初始化的值,針對(duì)這個(gè)需求,Nginx 定義了一系列的宏定義來(lái)代表各種配置所對(duì)應(yīng)數(shù)據(jù)類(lèi)型的未初始化值,如下:

    #define NGX_CONF_UNSET       -1
    #define NGX_CONF_UNSET_UINT  (ngx_uint_t) -1
    #define NGX_CONF_UNSET_PTR   (void *) -1
    #define NGX_CONF_UNSET_SIZE  (size_t) -1
    #define NGX_CONF_UNSET_MSEC  (ngx_msec_t) -1

又因?yàn)閷?duì)于配置項(xiàng)的合并,邏輯都類(lèi)似,也就是前面已經(jīng)說(shuō)過(guò)的,如果在本層次已經(jīng)配置了,也就是配置項(xiàng)的值已經(jīng)被讀取進(jìn)來(lái)了(那么這些配置項(xiàng)的值就不會(huì)等于上面已經(jīng)定義的那些 UNSET 的值),就使用本層次的值作為定義合并的結(jié)果,否則,使用上層的值,如果上層的值也是這些UNSET類(lèi)的值,那就賦值為默認(rèn)值,否則就使用上層的值作為合并的結(jié)果。對(duì)于這樣類(lèi)似的操作,Nginx 定義了一些宏操作來(lái)做這些事情,我們來(lái)看其中一個(gè)的定義。

    #define ngx_conf_merge_uint_value(conf, prev, default) \
        if (conf == NGX_CONF_UNSET_UINT) {      \
            conf = (prev == NGX_CONF_UNSET_UINT) ? default : prev; \
        }

顯而易見(jiàn),這個(gè)邏輯確實(shí)比較簡(jiǎn)單,所以其它的宏定義也類(lèi)似,我們就列具其中的一部分吧。

    ngx_conf_merge_value
    ngx_conf_merge_ptr_value
    ngx_conf_merge_uint_value
    ngx_conf_merge_msec_value
    ngx_conf_merge_sec_value

等等。

下面來(lái)看一下 hello 模塊的模塊上下文的定義,加深一下印象。

    static ngx_http_module_t ngx_http_hello_module_ctx = {
        NULL,                          /* preconfiguration */
        ngx_http_hello_init,           /* postconfiguration */

        NULL,                          /* create main configuration */
        NULL,                          /* init main configuration */

        NULL,                          /* create server configuration */
        NULL,                          /* merge server configuration */

        ngx_http_hello_create_loc_conf, /* create location configuration */
        NULL                        /* merge location configuration */
    };

注意:這里并沒(méi)有提供 merge_loc_conf 函數(shù),因?yàn)槲覀冞@個(gè)模塊的配置指令已經(jīng)確定只出現(xiàn)在 NGX_HTTP_LOC_CONF 中這一個(gè)層次上,不會(huì)發(fā)生需要合并的情況。

模塊的定義

對(duì)于開(kāi)發(fā)一個(gè)模塊來(lái)說(shuō),我們都需要定義一個(gè) ngx_module_t 類(lèi)型的變量來(lái)說(shuō)明這個(gè)模塊本身的信息,從某種意義上來(lái)說(shuō),這是這個(gè)模塊最重要的一個(gè)信息,它告訴了 Nginx 這個(gè)模塊的一些信息,上面定義的配置信息,還有模塊上下文信息,都是通過(guò)這個(gè)結(jié)構(gòu)來(lái)告訴 Nginx 系統(tǒng)的,也就是加載模塊的上層代碼,都需要通過(guò)定義的這個(gè)結(jié)構(gòu),來(lái)獲取這些信息。

我們先來(lái)看下 ngx_module_t 的定義

    typedef struct ngx_module_s      ngx_module_t;
    struct ngx_module_s {
        ngx_uint_t            ctx_index;
        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);
        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;
    };

    #define NGX_NUMBER_MAJOR  3
    #define NGX_NUMBER_MINOR  1
    #define NGX_MODULE_V1          0, 0, 0, 0,                              \
        NGX_DSO_ABI_COMPATIBILITY, NGX_NUMBER_MAJOR, NGX_NUMBER_MINOR
    #define NGX_MODULE_V1_PADDING  0, 0, 0, 0, 0, 0, 0, 0

再看一下 hello 模塊的模塊定義。

    ngx_module_t ngx_http_hello_module = {
        NGX_MODULE_V1,
        &ngx_http_hello_module_ctx,    /* module context */
        ngx_http_hello_commands,       /* module directives */
        NGX_HTTP_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
    };

模塊可以提供一些回調(diào)函數(shù)給 Nginx,當(dāng) Nginx 在創(chuàng)建進(jìn)程線程或者結(jié)束進(jìn)程線程時(shí)進(jìn)行調(diào)用。但大多數(shù)模塊在這些時(shí)刻并不需要做什么,所以都簡(jiǎn)單賦值為 NULL。