nginx的配置系統很靈活,不但支持模塊自定義配置項,而且支持多級配置以及合併多級配置項。這樣的設計使得nginx的配置在內存中的佈局也是分成多級的,比較複雜。因此,這裏採用一種自頂向下的方式進行逐級剖析。
這裏需要先說明一下nginx指令的上下文環境以及有效上下文環境。nginx配置的上下文環境指的是指令在配置文件中的位置,比如配置文件全局,http塊全局,http server塊, mail塊全局等。而nginx指令的有效上下文環境指的是指令在nginx配置文件中允許出現的位置。任何出現在其非有效上下文環境中的指令都會被nginx視爲錯誤。
下面來看一段代碼
struct ngx_cycle_s {
void ****conf_ctx;
...
};
ngx_cycle_s結構體的conf_ctx字段是nginx配置項的最頂層入口,它是一個四級指針。那麼,該怎麼去理解這個conf_ctx呢?
下面的代碼片段是從ngx_init_cycle函數中提取出來的,我們分析一下它的邏輯:
cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));//ngx_max_module是當前配置下nginx允許的最大模塊數
...
for (i = 0; cycle->modules[i]; i++) {
if (cycle->modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = cycle->modules[i]->ctx;
if (module->create_conf) {
rv = module->create_conf(cycle);
if (rv == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->conf_ctx[cycle->modules[i]->index] = rv;
}
}
可以看出,conf_ctx本身是一個數組,數組大小與當前配置下nginx允許的最大模塊數一致。另外,這裏還調用了類型爲NGX_CORE_MODULE的模塊ctx成員的create_conf回調函數,並且把返回值保存在模塊在conf_ctx中對應的元素中。而這個create_conf回調函數是NGX_CORE_MODULE類型的模塊實現配置環境創建的,也就是說,NGX_CORE_MODULE類型的模塊的配置是保存在conf_ctx與其位置對應的元素中的。那麼,哪些模塊是NGX_CORE_MODULE呢?下表列出了到nginx-1.12.1爲止的NGX_CORE_MODULE以及它們的源碼文件和create_conf返回的實際類型:
ngx_core_module | nginx.c | ngx_core_conf_t * |
ngx_events_module | ngx_event.c | void *** |
ngx_openssl_module | ngx_event_openssl.c | ngx_openssl_conf_t * |
ngx_google_perftools_module | ngx_google_perftools_module.c | ngx_google_perftools_conf_t * |
ngx_http_module | ngx_http.c | ngx_http_conf_ctx_t * |
ngx_errlog_module | ngx_log.c | NULL |
ngx_mail_module | ngx_mail.c | ngx_mail_conf_ctx_t * |
ngx_regex_module | ngx_regex.c | ngx_regex_conf_t * |
ngx_stream_module | ngx_stream.c | ngx_stream_conf_ctx_t * |
ngx_thread_pool_module | ngx_thread_pool.c | ngx_thread_pool_conf_t * |
那麼NGX_CORE_MODULE中的指令的有效上下文環境是什麼呢?很容易可以想到,就是配置文件全局。也就是說,任何在NGX_CORE_MODULE類型的模塊中定義的指令只能出現在配置文件最外層,不能出現在其它任何 位置。
到這裏我們已經可以知道,出現在最外層的配置都會被直接保存在conf_ctx對應的元素指向的內存塊中。下面是從conf_ctx的角度上看,各主要NGX_CORE_MODULE類型模塊的內存佈局圖:
那麼,非全局的配置會被保存在哪裏呢?這與模塊類型相關,不同類型的模塊的配置內存佈局各不相同,會在別的文章中單獨分析。