萬盛學電腦網

 萬盛學電腦網 >> 服務器教程 >> Nginx 配置文件解析

Nginx 配置文件解析

  cycle = ngx_init_cycle(&init_cycle):

  1、在內存池中分配一個ngx_cycle_t變量,並初始化它的各個成員。

  2、調用core類型的create_conf,實際只有一個ngx_core_module_create_conf函數----初始化ngx_core_conf_t結構(存放core_module支持的指令),保存在ngx_cycle->conf_ctx數組中。可以說,此時,ngx_cycle->conf_ctx數組中只有一個ngx_core_conf_t結構。

  3、初始化ngx_conf_t結構。

  4、ngx_conf_parse 解析配置文件,把結果保存在模塊對應的ngx_conf裡面。

  5、調用core類型的init_conf,實際只有一個ngx_core_module_init_conf函數(初始化對應的ngx_core_conf_t函數)。為什麼要init,都已經解析配置文件了,應該在這之前初始化呀--如果值為-1,表明沒有設置,初始化默認值!

  6、ngx_open_listening_sockets:遍歷listening數組並打開所有偵聽sockets(socket()->setsockopt()->bind()->listen())。

  7、調用所有模塊的init_module(實際上只有ngx_event_core_module模塊定義了該callback,即只有ngx_event_module_init()被調用)。

  ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename):

  函數的作用就是循環不停的從配置文件中讀取指令,然後進行指令處理,直到結束

  1、先分析ngx_core_module的指令及其對應的set函數。

  { ngx_string("daemon"),

  NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,

  ngx_conf_set_flag_slot,

  0,

  offsetof(ngx_core_conf_t, daemon),

  //計算daemon成員在ngx_core_conf_t結構體裡面的偏移

  NULL },

  ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf):裡面代碼很清楚,根據配置指令,設置模塊conf結構的成員變量。

  2、分析ngx_events_modules的指令及其對應的set函數。只有一條指令:

  { ngx_string("events"),

  NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,

  ngx_events_block,

  0,

  0,

  NULL },

  1、ngx_events_module編號為3,於是ngx_cycle->conf_ctx指向的void*數組第3號槽位指向一個void*指針,這個指針又指向一個void*數組(個數==事件類型模塊的個數,Linux平台編譯之後,只有兩個ngx_epoll_module事件模型ngx_event_core_module和ngx_epoll_module)。

  2、調用event類型模塊的上下文ngx_event_module_t 的create_conf鉤子,為void*數組指定槽位創建相應的conf結構。

  3、更改當前cf環境(NGX_EVENT_MODULE,NGX_EVENT_CONF)解析events{ 塊裡面的指令。裡面的set函數都是根據配置文件設置ngx_event_conf_t結構體裡面的成員變量。

  3、分析ngx_http_module的指令及其對應的set函數。只有一條指令,如下:

  { ngx_string("http"),

  NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,

  ngx_http_block,

  0,

  0,

  NULL },

  ngx_init_cycle創建了core module的config,那麼http module相關的config在那裡創建呢?http module相關的config是在ngx_http_block中創建(ngx_http_conf_ctx_t)的,在ngx_http_block中會創建,初始化,合並config(未完全看懂),以及整個http handler phase的初始化(還未看)等等。

 

1、為ngx_cycle->conf_ctx指向的void*數組創建ngx_http_conf_ctx_t結構,並為ngx_http_conf_ctx_t 創建main_conf srv_conf loc_conf三個void*數組,數組大小為http類型模塊的個數。
2、遍歷所有的http類型的模塊的上下文ngx_http_module_t,調用create_main_conf、create_srv_conf、create_loc_conf 分別在ngx_http_conf_ctx_t 的三個數組(main_conf srv_conf loc_conf)的對應槽位創建響應的結構體變量。
3、遍歷所有的http類型的模塊的上下文ngx_http_module_t, 調用 preconfiguration 鉤子函數。
4、解析http塊裡面的指令:ngx_conf_parse 未看,當前環境:ctx指向ngx_http_conf_ctx_t,指令類型為NGX_HTTP_MAIN_CONF,模塊類型為:NGX_HTTP_MODULE。
4.1、 遇到http裡面的main指令:
if (cmd->type & NGX_DIRECT_CONF) {
conf = ((void **) cf->ctx)[ngx_modules[i]->index]; //ngx_core_conf_t
} else if (cmd->type & NGX_MAIN_CONF) {
//hp: 比如,遇到http/events指令,這裡,conf指向的是cf->ctx的第idx個槽位
conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
} else if (cf->ctx) {
//否則進入二級模塊處理,比如events/http {裡面的指令,都是在這裡

//http 裡面的main指令,ctx指向於ngx_http_conf_ctx_t
confp = *(void **) ((char *) cf->ctx + cmd->conf); //這裡,cmd->conf的作用體現出來了
if (confp) {
//http裡面的main指令: conf指向的是對應的ngx_http_core_main_conf_t
conf = confp[ngx_modules[i]->ctx_index];
}
}
比如variables_hash_max_size 指令:
{ ngx_string("variables_hash_max_size"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot, //這裡,剛好設置conf(ngx_http_core_main_conf_t) 的variables_hash_max_size的值。
NGX_HTTP_MAIN_CONF_OFFSET, //這裡,conf+NGX_HTTP_MAIN_CONF_OFFSET就是需要設置的結構體==ngx_http_core_main_conf_t變量地址
offsetof(ngx_http_core_main_conf_t, variables_hash_max_size), //需要設置結構體中的哪個成員,成員在結構體中的偏移。
NULL },
總結出struct ngx_command_s { // 這個域主要是供nginx解析配置文件時使用,設置相關的數據結構
ngx_str_t name;
//命令名稱
ngx_uint_t type;
//命令類型(有幾個參數等)
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); //這個conf指向需要設置的結構體變量地址
ngx_uint_t conf;
//配置結構體在內存的位置,相對於conf的偏移量,在ngx_conf_handler中使用
ngx_uint_t offset;
//要設置結構體的哪個成員,相對於結構體的偏移量
void *post;
 

  //一些讀取配置時候的零碎變量,一般為null

  };

  4.2 遇到 server指令時:

  生成一個新的ngx_http_conf_ctx_t,其中main_conf指向原來的,server_conf和loc_conf創建新的void*數組。把ngx_http_core_module的server塊配置信息存入 main_conf 中的server 容器裡面。更新當前環境。 開始解析server塊裡面的指令。

  cf->ctx = ctx; //指向新的ngx_http_conf_ctx_t

  cf->cmd_type = NGX_HTTP_SRV_CONF;

  4.3 遇到server裡面的指令:遇到listen 指令時,ngx_conf_handler中,confp指向的新的ngx_http_conf_ctx_t.srv_conf所指向的void*數組,於是 conf = confp[ngx_modules[i]->ctx_index];指向listen指令對應的模塊(ngx_htt_core_module)的 ngx_http_core_srv_conf_t數據結構。

  4.4 遇到location指令:生成一個新的ngx_http_conf_ctx_t,其中main_conf指向原來的,srv_conf指向上一層ngx_http_conf_ctx_t的srv_conf數組,loc_conf創建新的void*數組。

  ngx_http_core_location 這個函數很麻煩,看起來主要是設置ngx_http_loc_conf_ctx_t裡面的name變量。然後遞歸調用ngx_parse_conf解析location裡面的命令。

  4.5: 遇到location裡面的命令。比如 root,設置ngx_http_loc_conf_ctx_t裡面的root變量。

  5、回到ngx_http_block函數!遍歷每個http類型的模塊,調用模塊上下文ngx_http_module_t中的init_main_conf鉤子初始化模塊對應的main_conf配置信息,然後調用ngx_http_merge_servers。

copyright © 萬盛學電腦網 all rights reserved