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_PREFIXp = 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_PREFIXngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX); #elsengx_str_set(&cycle->conf_prefix, NGX_PREFIX); #endifngx_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_PREFIXp = 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_PREFIXngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX); #elsengx_str_set(&cycle->conf_prefix, NGX_PREFIX); #endifngx_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; }返回成功状态。