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

返回成功状态。

相关推荐
铁锅与大鹅22 分钟前
http+nginx
网络协议·nginx·http
马剑威(威哥爱编程)42 分钟前
Linux驱动开发13个实用案例
linux·运维·驱动开发
程序员JerrySUN1 小时前
每天设计者模式-1:基础面试题
java·linux·运维·服务器·开发语言·python·docker
千墨2 小时前
VMware安装Centos 9虚拟机+设置共享文件夹+远程登录
linux·运维·centos
s_fox_3 小时前
Nginx Embedded Variables 嵌入式变量解析(4)
java·网络·nginx
网络安全(华哥)3 小时前
网络安全服务实施流程管理 网络安全服务体系
运维·服务器·网络
致奋斗的我们3 小时前
Nginx反向代理及负载均衡
linux·运维·mysql·nginx·负载均衡·shell·openeluer
Ares-Wang4 小时前
负载均衡 方式
运维·负载均衡
钗头风4 小时前
3.Docker常用命令
运维·docker·容器
朝九晚五ฺ4 小时前
【Linux探索学习】第三十弹——线程互斥与同步(上):深入理解线程保证安全的机制
linux·运维·学习