定義在?src\core\ngx_conf_file.c
static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{char *rv;void *conf, **confp;ngx_uint_t i, found;ngx_str_t *name;ngx_command_t *cmd;name = cf->args->elts;found = 0;for (i = 0; cf->cycle->modules[i]; i++) {cmd = cf->cycle->modules[i]->commands;if (cmd == NULL) {continue;}for ( /* void */ ; cmd->name.len; cmd++) {if (name->len != cmd->name.len) {continue;}if (ngx_strcmp(name->data, cmd->name.data) != 0) {continue;}found = 1;if (cf->cycle->modules[i]->type != NGX_CONF_MODULE&& cf->cycle->modules[i]->type != cf->module_type){continue;}/* is the directive's location right ? */if (!(cmd->type & cf->cmd_type)) {continue;}if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"directive \"%s\" is not terminated by \";\"",name->data);return NGX_ERROR;}if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"directive \"%s\" has no opening \"{\"",name->data);return NGX_ERROR;}/* is the directive's argument count right ? */if (!(cmd->type & NGX_CONF_ANY)) {if (cmd->type & NGX_CONF_FLAG) {if (cf->args->nelts != 2) {goto invalid;}} else if (cmd->type & NGX_CONF_1MORE) {if (cf->args->nelts < 2) {goto invalid;}} else if (cmd->type & NGX_CONF_2MORE) {if (cf->args->nelts < 3) {goto invalid;}} else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {goto invalid;} else if (!(cmd->type & argument_number[cf->args->nelts - 1])){goto invalid;}}/* set up the directive's configuration context */conf = NULL;if (cmd->type & NGX_DIRECT_CONF) {conf = ((void **) cf->ctx)[cf->cycle->modules[i]->index];} else if (cmd->type & NGX_MAIN_CONF) {conf = &(((void **) cf->ctx)[cf->cycle->modules[i]->index]);} else if (cf->ctx) {confp = *(void **) ((char *) cf->ctx + cmd->conf);if (confp) {conf = confp[cf->cycle->modules[i]->ctx_index];}}rv = cmd->set(cf, cmd, conf);if (rv == NGX_CONF_OK) {return NGX_OK;}if (rv == NGX_CONF_ERROR) {return NGX_ERROR;}ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"\"%s\" directive %s", name->data, rv);return NGX_ERROR;}}if (found) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"\"%s\" directive is not allowed here", name->data);return NGX_ERROR;}ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"unknown directive \"%s\"", name->data);return NGX_ERROR;invalid:ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid number of arguments in \"%s\" directive",name->data);return NGX_ERROR;
}
ngx_conf_handler
?是 Nginx 配置解析的核心函數,其主要作用是根據當前解析到的配置指令,找到對應的模塊命令并執行相關校驗和設置
name = cf->args->elts;found = 0;
?name = cf->args->elts;
將當前配置指令的參數列表(數組)的起始地址賦值給 name 指針,以便后續遍歷和匹配指令名。found = 0;
初始化標志變量 found 為 0,表示尚未找到與當前配置指令匹配的模塊命令。found 是一個布爾標記,用于記錄是否在模塊的指令列表中成功匹配到當前指令名。
初始值為 0(未找到),在后續遍歷模塊的 commands 數組時,若匹配到指令名,則置為 1
此時
name->data=worker_processes
worker_processes?用于定義 Nginx 工作進程(Worker Processes)的數量
- 每個
worker_process
是一個獨立的進程,負責處理客戶端請求。- 多進程設計 :通過啟用多個工作進程,Nginx 可以充分利用多核 CPU 的性能,實現高并發處理。
- 默認值 :
1
(但通常建議根據服務器 CPU 核心數調整)。
for (i = 0; cf->cycle->modules[i]; i++) {cmd = cf->cycle->modules[i]->commands;if (cmd == NULL) {continue;}
?遍歷 Nginx 所有已加載的模塊,檢查每個模塊是否包含需要處理的配置指令。
獲取模塊的指令列表:cmd = cf->cycle->modules[i]->commands;
獲取當前模塊支持的配置指令列表(commands 數組),用于后續匹配當前解析的指令。commands 是 ngx_module_t 結構體的成員,指向一個 ngx_command_t 數組,表示該模塊支持的配置指令。
cmd 是 ngx_command_t* 類型指針,指向當前模塊的指令列表。
后續內層循環會遍歷 cmd 數組,匹配當前配置指令名。跳過無指令的模塊:if (cmd == NULL) { continue; }
如果當前模塊沒有定義任何配置指令(commands 為 NULL),則跳過該模塊,繼續檢查下一個模塊。
某些模塊可能不處理配置指令(例如僅提供功能的模塊),其 commands 字段會被設為 NULL。意圖
遍歷所有模塊
通過外層循環,確保每個模塊都有機會檢查是否支持當前解析的配置指令。篩選有效模塊
僅處理包含配置指令(commands 非空)的模塊,忽略無指令的模塊。為內層循環做準備
每個模塊的 commands 數組將在內層循環中被遍歷,逐個匹配指令名
for ( /* void */ ; cmd->name.len; cmd++) {
?遍歷當前模塊的指令列表(
commands
?數組),逐個匹配當前解析的配置指令名。
cmd->name.len
?為 0 時,表示已遍歷到指令列表的末尾(每個模塊的?commands
?數組以?cmd->name.len = 0
?的哨兵元素結束)。
?
if (name->len != cmd->name.len) {continue;}
如果長度不同,說明指令名一定不匹配,直接跳過當前?
cmd
if (ngx_strcmp(name->data, cmd->name.data) != 0) {continue;}
?
比較當前配置指令名與模塊定義的指令名是否完全一致。
返回值為 0 表示字符串內容完全相同,說明找到匹配的指令。
若名稱不匹配,跳過當前指令,繼續檢查下一個?
cmd
ngx_strcmp
ngx_strcmp-CSDN博客
found = 1;
?找到了 匹配的指令
此時
cf->cycle->modules[0]->name=ngx_core_module
?
if (cf->cycle->modules[i]->type != NGX_CONF_MODULE&& cf->cycle->modules[i]->type != cf->module_type){continue;}
如果當前模塊類型?既不是通用配置模塊,也不匹配當前配置階段的模塊類型(
cf->module_type
),則跳過該指令
?此時
cf->cycle->modules[0]->type=0x45524F43
cf->module_type=0x45524F43
NGX_CONF_MODULE=0x464E4F43
0x45524F43 是?NGX_CORE_MODULE
./nginx-1.24.0/src/core/ngx_conf_file.h:70:#define NGX_CORE_MODULE 0x45524F43 /* "CORE" */
條件不成立
/* is the directive's location right ? */if (!(cmd->type & cf->cmd_type)) {continue;}
驗證 配置指令出現的位置
cmd->type 表示該指令預期可以出現的位置
cf->cmd_type 表示當前配置文件中的位置
此時
cmd->type? ? ?=0x1010002
cf->cmd_type=0x1000000 (NGX_MAIN_CONF)./nginx-1.24.0/src/core/ngx_conf_file.h:51:#define NGX_MAIN_CONF 0x01000000
?
if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"directive \"%s\" is not terminated by \";\"",name->data);return NGX_ERROR;}
檢查非塊指令是否以分號結尾
cmd->type & NGX_CONF_BLOCK
NGX_CONF_BLOCK
?是塊指令標志,若未設置,說明當前指令是非塊指令。last != NGX_OK
last
?參數表示解析器的狀態:
NGX_OK
:正常結束(指令以分號?;
?結尾)。
#define NGX_CONF_BLOCK 0x00000100
此時
last=0 (
NGX_OK
)
if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"directive \"%s\" has no opening \"{\"",name->data);return NGX_ERROR;}
?若指令是塊類型,但未以?
{
?開始(last
?非?NGX_CONF_BLOCK_START
),則觸發錯誤:
#define NGX_CONF_BLOCK_START 1
?
當前指令不是塊類型
?
/* is the directive's argument count right ? */if (!(cmd->type & NGX_CONF_ANY)) {
檢查指令的參數數量
NGX_CONF_ANY
?表示指令允許任意數量參數不是?允許任意數量參數?
進入進一步的檢查
此時條件成立
cf->args->nelts=2
if (cmd->type & NGX_CONF_FLAG) {if (cf->args->nelts != 2) {goto invalid;}}
?
NGX_CONF_FLAG
?表示指令需要一個布爾值參數。- 布爾指令的完整格式為?
指令名 參數
,參數數量必須為 2(例如?rewrite_log on;)
此時條件不成立
else if (cmd->type & NGX_CONF_1MORE) {if (cf->args->nelts < 2) {goto invalid;}}
NGX_CONF_1MORE
?表示指令需要至少 1 個參數
此時條件不成立
} else if (cmd->type & NGX_CONF_2MORE) {if (cf->args->nelts < 3) {goto invalid;}}
NGX_CONF_2MORE
?表示指令需要至少 2 個參數
此時條件不成立
} else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {goto invalid;}
檢查參數總數是否超過允許的最大值
此時條件不成立
} else if (!(cmd->type & argument_number[cf->args->nelts - 1])){goto invalid;}
?精確匹配參數數量(當前指令的參數數量是固定的而不是 至少一個這種不固定的)
argument_number
?是一個預定義的數組,將參數數量映射到對應的標志位。例如static ngx_uint_t argument_number[] = {NGX_CONF_NOARGS, // 0 參數(僅指令名)NGX_CONF_TAKE1, // 1 參數NGX_CONF_TAKE2, // 2 參數// ... 其他 };
cf->args->nelts - 1
?將參數總數轉換為實際參數數量(減去指令名)
此時條件不成立
通過了參數數量的校驗
?
/* set up the directive's configuration context */conf = NULL;if (cmd->type & NGX_DIRECT_CONF) {conf = ((void **) cf->ctx)[cf->cycle->modules[i]->index];
為指令(
cmd
)設置配置上下文(conf
),并調用指令的?set
?方法將配置值寫入上下文。
根據指令類型選擇不同的配置存儲位置,最終處理?set
?方法的返回值。
NGX_DIRECT_CONF
是一種指令類型,用于定義必須直接出現在配置文件頂層(全局作用域)的指令,而不是嵌套在http
、server
、location
等子配置塊中?
NGX_DIRECT_CONF
?指令的配置結構指針直接存儲在模塊的配置數組中
此時 條件成立
cf->cycle->modules[0]->index=0
rv = cmd->set(cf, cmd, conf);
?調用指令的?
set
?方法,解析指令,然后設置其所在配置結構的對應字段
當前指令是 worker_processes
worker_processes 指令的 set 函數
worker_processes 指令的 set 函數-CSDN博客
if (rv == NGX_CONF_OK) {return NGX_OK;}
?返回 NGX_OK ,代表 指令處理成功