Ubuntu 下 nginx-1.24.0 源码分析 - ngx_process_options

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 启动过程中用于处理命令行选项的函数
主要逻辑

  1. 处理前缀路径 (ngx_prefix)

    • 如果用户指定了 ngx_prefix,则检查是否需要添加路径分隔符 /
    • 如果未指定 ngx_prefix,则根据编译时的宏定义(如 NGX_PREFIXNGX_CONF_PREFIX)或当前工作目录设置默认路径。
  2. 处理配置文件路径 (ngx_conf_file)

    • 如果用户指定了 ngx_conf_file,则使用该路径。
    • 如果未指定,则使用默认路径 NGX_CONF_PATH
    • 调用 ngx_conf_full_name 将路径转换为完整路径,并提取配置文件所在目录作为 conf_prefix
  3. 处理错误日志路径 (ngx_error_log)

    • 如果用户指定了 ngx_error_log,则使用该路径。
    • 如果未指定,则使用默认路径 NGX_ERROR_LOG_PATH
  4. 处理额外配置参数 (ngx_conf_params)

    • 如果用户提供了额外的配置参数,则将其存储到 cycle->conf_param
  5. 测试模式 (ngx_test_config)

    • 如果启用了测试模式,则调整日志级别为 NGX_LOG_INFO
  6. 返回结果

    • 如果所有步骤成功完成,则返回 NGX_OK;否则返回 NGX_ERROR

详解

函数定义

复制代码
static ngx_int_t
ngx_process_options(ngx_cycle_t *cycle)

参数cycle 是 Nginx 的核心结构体,保存全局配置和运行时状态

返回值ngx_int_t 表示处理状态(NGX_OKNGX_ERROR
变量声明

复制代码
    u_char  *p;
    size_t   len;

定义局部变量 plen

  • 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 不以 / 结尾:

    1. 分配一块新的内存空间,大小为 len + 1
    2. 将原始路径复制到新分配的内存中
    3. 在末尾追加 / 并更新长度 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_prefixcycle->prefix

  • conf_prefixprefix 都表示 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
    1. 动态获取当前工作目录(ngx_getcwd)。
    2. 确保路径以 / 结尾。
    3. 将结果赋值给 conf_prefixprefix
  • 定义了 NGX_PREFIX
    1. 使用预定义的路径(NGX_PREFIXNGX_CONF_PREFIX)。
    2. 调用 ngx_str_set 将路径赋值给 conf_prefixprefix

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;
}

返回成功状态。

相关推荐
草莓熊Lotso9 小时前
Linux 文件描述符与重定向实战:从原理到 minishell 实现
android·linux·运维·服务器·数据库·c++·人工智能
历程里程碑9 小时前
Linux22 文件系统
linux·运维·c语言·开发语言·数据结构·c++·算法
七夜zippoe17 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
Fcy64818 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满18 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠19 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
Harvey90319 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
珠海西格电力科技20 小时前
微电网能量平衡理论的实现条件在不同场景下有哪些差异?
运维·服务器·网络·人工智能·云计算·智慧城市
释怀不想释怀20 小时前
Linux环境变量
linux·运维·服务器
zzzsde20 小时前
【Linux】进程(4):进程优先级&&调度队列
linux·运维·服务器