ngx_process_options
声明在 src\core\nginx.c
static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
定义在 src\core\nginx.c
static ngx_int_t ngx_process_options(ngx_cycle_t *cycle) { u_char *p; size_t len; if (ngx_prefix) { len = ngx_strlen(ngx_prefix); p = ngx_prefix; if (len && !ngx_path_separator(p[len - 1])) { p = ngx_pnalloc(cycle->pool, len + 1); if (p == NULL) { return NGX_ERROR; } ngx_memcpy(p, ngx_prefix, len); p[len++] = '/'; } cycle->conf_prefix.len = len; cycle->conf_prefix.data = p; cycle->prefix.len = len; cycle->prefix.data = p; } else { #ifndef NGX_PREFIX p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH); if (p == NULL) { return NGX_ERROR; } if (ngx_getcwd(p, NGX_MAX_PATH) == 0) { ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed"); return NGX_ERROR; } len = ngx_strlen(p); p[len++] = '/'; cycle->conf_prefix.len = len; cycle->conf_prefix.data = p; cycle->prefix.len = len; cycle->prefix.data = p; #else #ifdef NGX_CONF_PREFIX ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX); #else ngx_str_set(&cycle->conf_prefix, NGX_PREFIX); #endif ngx_str_set(&cycle->prefix, NGX_PREFIX); #endif } if (ngx_conf_file) { cycle->conf_file.len = ngx_strlen(ngx_conf_file); cycle->conf_file.data = ngx_conf_file; } else { ngx_str_set(&cycle->conf_file, NGX_CONF_PATH); } if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) { return NGX_ERROR; } for (p = cycle->conf_file.data + cycle->conf_file.len - 1; p > cycle->conf_file.data; p--) { if (ngx_path_separator(*p)) { cycle->conf_prefix.len = p - cycle->conf_file.data + 1; cycle->conf_prefix.data = cycle->conf_file.data; break; } } if (ngx_error_log) { cycle->error_log.len = ngx_strlen(ngx_error_log); cycle->error_log.data = ngx_error_log; } else { ngx_str_set(&cycle->error_log, NGX_ERROR_LOG_PATH); } if (ngx_conf_params) { cycle->conf_param.len = ngx_strlen(ngx_conf_params); cycle->conf_param.data = ngx_conf_params; } if (ngx_test_config) { cycle->log->log_level = NGX_LOG_INFO; } return NGX_OK; }
ngx_process_options
是 Nginx 启动过程中用于处理命令行选项的函数
主要逻辑
处理前缀路径 (
ngx_prefix
):
- 如果用户指定了
ngx_prefix
,则检查是否需要添加路径分隔符/
。- 如果未指定
ngx_prefix
,则根据编译时的宏定义(如NGX_PREFIX
和NGX_CONF_PREFIX
)或当前工作目录设置默认路径。处理配置文件路径 (
ngx_conf_file
):
- 如果用户指定了
ngx_conf_file
,则使用该路径。- 如果未指定,则使用默认路径
NGX_CONF_PATH
。- 调用
ngx_conf_full_name
将路径转换为完整路径,并提取配置文件所在目录作为conf_prefix
。处理错误日志路径 (
ngx_error_log
):
- 如果用户指定了
ngx_error_log
,则使用该路径。- 如果未指定,则使用默认路径
NGX_ERROR_LOG_PATH
。处理额外配置参数 (
ngx_conf_params
):
- 如果用户提供了额外的配置参数,则将其存储到
cycle->conf_param
。测试模式 (
ngx_test_config
):
- 如果启用了测试模式,则调整日志级别为
NGX_LOG_INFO
。返回结果:
- 如果所有步骤成功完成,则返回
NGX_OK
;否则返回NGX_ERROR
。详解
函数定义
static ngx_int_t ngx_process_options(ngx_cycle_t *cycle)
参数 :
cycle
是 Nginx 的核心结构体,保存全局配置和运行时状态返回值 :
ngx_int_t
表示处理状态(NGX_OK
或NGX_ERROR
)
变量声明u_char *p; size_t len;
定义局部变量
p
和len
。
p
:临时指针,用于操作路径字符串。
len
:路径字符串的长度。
处理
ngx_prefix
(路径前缀)if (ngx_prefix) { len = ngx_strlen(ngx_prefix); p = ngx_prefix;
检查是否指定了
ngx_prefix
(即用户通过命令行或编译时指定的工作目录)。
如果
ngx_prefix
存在,则计算其长度并将其赋值给p
确保路径以路径分隔符/
结尾if (len && !ngx_path_separator(p[len - 1])) { p = ngx_pnalloc(cycle->pool, len + 1); if (p == NULL) { return NGX_ERROR; } ngx_memcpy(p, ngx_prefix, len); p[len++] = '/'; }
如果
ngx_prefix
不以/
结尾:
- 分配一块新的内存空间,大小为
len + 1
- 将原始路径复制到新分配的内存中
- 在末尾追加
/
并更新长度len
ngx_path_separator
定义在 src/os/unix/ngx_files.h 中
#define ngx_path_separator(c) ((c) == '/')
ngx_pnalloc
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_pnalloc函数-CSDN博客
cycle->conf_prefix.len = len; cycle->conf_prefix.data = p; cycle->prefix.len = len; cycle->prefix.data = p; } else {
将处理后的路径赋值给
cycle->conf_prefix
和cycle->prefix
。
conf_prefix
和prefix
都表示 Nginx 的工作目录。如果未指定
ngx_prefix
,则进入else
分支。#ifndef NGX_PREFIX
p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
if (p == NULL) {
return NGX_ERROR;
}
if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {
ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
return NGX_ERROR;
}
len = ngx_strlen(p);
p[len++] = '/';
cycle->conf_prefix.len = len;
cycle->conf_prefix.data = p;
cycle->prefix.len = len;
cycle->prefix.data = p;
#else
#ifdef NGX_CONF_PREFIX
ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);
#else
ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
#endif
ngx_str_set(&cycle->prefix, NGX_PREFIX);
#endif根据是否定义了
NGX_PREFIX
宏,选择不同的路径初始化方式。
- 未定义
NGX_PREFIX
:
- 动态获取当前工作目录(
ngx_getcwd
)。- 确保路径以
/
结尾。- 将结果赋值给
conf_prefix
和prefix
。- 定义了
NGX_PREFIX
:
- 使用预定义的路径(
NGX_PREFIX
或NGX_CONF_PREFIX
)。- 调用
ngx_str_set
将路径赋值给conf_prefix
和prefix
。
ngx_str_set
定义在 src\core\ngx_string.h
#define ngx_str_set(str, text) \ (str)->len = sizeof(text) - 1; (str)->data = (u_char *) text if (ngx_conf_file) { cycle->conf_file.len = ngx_strlen(ngx_conf_file); cycle->conf_file.data = ngx_conf_file; } else { ngx_str_set(&cycle->conf_file, NGX_CONF_PATH); }
设置配置文件路径。
如果用户指定了
ngx_conf_file
,则使用用户提供的路径。否则,使用默认路径
NGX_CONF_PATH
。if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) { return NGX_ERROR; }
将配置文件路径转换为绝对路径。
- 调用
ngx_conf_full_name
函数完成路径标准化。- 如果失败,返回错误。
ngx_conf_full_name
该函数的主要作用是将相对路径转换为绝对路径
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_conf_full_name 函数-CSDN博客
for (p = cycle->conf_file.data + cycle->conf_file.len - 1; p > cycle->conf_file.data; p--) { if (ngx_path_separator(*p)) { cycle->conf_prefix.len = p - cycle->conf_file.data + 1; cycle->conf_prefix.data = cycle->conf_file.data; break; } }
从配置文件路径中提取配置目录。
从路径末尾向前遍历,找到最后一个路径分隔符
/
。将分隔符之前的部分作为
conf_prefix
。if (ngx_error_log) { cycle->error_log.len = ngx_strlen(ngx_error_log); cycle->error_log.data = ngx_error_log; } else { ngx_str_set(&cycle->error_log, NGX_ERROR_LOG_PATH); }
设置错误日志路径。
如果用户指定了
ngx_error_log
,则使用用户提供的路径。否则,使用默认路径
NGX_ERROR_LOG_PATH
if (ngx_conf_params) { cycle->conf_param.len = ngx_strlen(ngx_conf_params); cycle->conf_param.data = ngx_conf_params; }
设置额外的配置参数。
如果用户指定了
ngx_conf_params
,则将其赋值给cycle->conf_param
if (ngx_test_config) { cycle->log->log_level = NGX_LOG_INFO; }
如果启用了测试模式(
ngx_test_config
),将日志级别设置为INFO
return NGX_OK; }
返回成功状态。