目录

Ubuntu-下-nginx-1.24.0-源码分析-1

目录

Ubuntu 下 nginx-1.24.0 源码分析 (1)

main 函数在

src\core\nginx.c


int ngx_cdecl
main(int argc, char *const *argv)
{
    ngx_buf_t        *b;
    ngx_log_t        *log;
    ngx_uint_t        i;
    ngx_cycle_t      *cycle, init_cycle;
    ngx_conf_dump_t  *cd;
    ngx_core_conf_t  *ccf;

    ngx_debug_init();

进入 main 函数

最开始是局部变量的声明

然后是


接下来是 :

   if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }


接下来是 :

    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

当前这次执行的是:

sudo ./nginx

除了 程序名 没有其他参数

所以

argc=1

于是在 ngx_get_options 函数中

static ngx_int_t
ngx_get_options(int argc, char *const *argv)
{
    u_char     *p;
    ngx_int_t   i;

    for (i = 1; i < argc; i++) {

        p = (u_char *) argv[i];

        if (*p++ != '-') {
            ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
            return NGX_ERROR;
        }

        while (*p) {

            switch (*p++) {

            case '?':
            case 'h':
                ngx_show_version = 1;
                ngx_show_help = 1;
                break;

            case 'v':
                ngx_show_version = 1;
                break;

            case 'V':
                ngx_show_version = 1;
                ngx_show_configure = 1;
                break;

            case 't':
                ngx_test_config = 1;
                break;

            case 'T':
                ngx_test_config = 1;
                ngx_dump_config = 1;
                break;

            case 'q':
                ngx_quiet_mode = 1;
                break;

            case 'p':
                if (*p) {
                    ngx_prefix = p;
                    goto next;
                }

                if (argv[++i]) {
                    ngx_prefix = (u_char *) argv[i];
                    goto next;
                }

                ngx_log_stderr(0, "option \"-p\" requires directory name");
                return NGX_ERROR;

            case 'e':
                if (*p) {
                    ngx_error_log = p;

                } else if (argv[++i]) {
                    ngx_error_log = (u_char *) argv[i];

                } else {
                    ngx_log_stderr(0, "option \"-e\" requires file name");
                    return NGX_ERROR;
                }

                if (ngx_strcmp(ngx_error_log, "stderr") == 0) {
                    ngx_error_log = (u_char *) "";
                }

                goto next;

            case 'c':
                if (*p) {
                    ngx_conf_file = p;
                    goto next;
                }

                if (argv[++i]) {
                    ngx_conf_file = (u_char *) argv[i];
                    goto next;
                }

                ngx_log_stderr(0, "option \"-c\" requires file name");
                return NGX_ERROR;

            case 'g':
                if (*p) {
                    ngx_conf_params = p;
                    goto next;
                }

                if (argv[++i]) {
                    ngx_conf_params = (u_char *) argv[i];
                    goto next;
                }

                ngx_log_stderr(0, "option \"-g\" requires parameter");
                return NGX_ERROR;

            case 's':
                if (*p) {
                    ngx_signal = (char *) p;

                } else if (argv[++i]) {
                    ngx_signal = argv[i];

                } else {
                    ngx_log_stderr(0, "option \"-s\" requires parameter");
                    return NGX_ERROR;
                }

                if (ngx_strcmp(ngx_signal, "stop") == 0
                    || ngx_strcmp(ngx_signal, "quit") == 0
                    || ngx_strcmp(ngx_signal, "reopen") == 0
                    || ngx_strcmp(ngx_signal, "reload") == 0)
                {
                    ngx_process = NGX_PROCESS_SIGNALLER;
                    goto next;
                }

                ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal);
                return NGX_ERROR;

            default:
                ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
                return NGX_ERROR;
            }
        }

    next:

        continue;
    }

    return NGX_OK;
}

进入不了 for 循环

直接走到

return NGX_OK;

返回到 main 函数中


接下来是 :

if (ngx_show_version) {
        ngx_show_version_info();

        if (!ngx_test_config) {
            return 0;
        }
    }

ngx_show_version 未设置,此时是 0

于是跳过这段代码


接下来是 :

/* TODO */ ngx_max_sockets = -1;

初始化全局变量 ngx_max_sockets

ngx_max_sockets 是一个全局变量,用于存储 Nginx 能够处理的最大文件描述符(socket)数量。

文件描述符 是操作系统用于管理打开的文件、socket 等资源的标识符。Nginx 作为一个高性能的 Web 服务器,需要处理大量的并发连接,因此文件描述符的数量对性能有重要影响

初始值为 -1 的意义

  • ngx_max_sockets 初始化为 -1 表示在程序启动时,还没有确定实际的最大文件描述符数量。

  • -1 通常用作一个初始值或无效值,表示该变量 尚未被正确初始化或配置 。

  • 在后续的代码中,Nginx 会根据操作系统的限制和配置文件中的设置来更新 ngx_max_sockets 的值。


接下来是 :

ngx_time_init();


接下来是 :

#if (NGX_PCRE)
    ngx_regex_init();
#endif


接下来是 :

    ngx_pid = ngx_getpid();
    ngx_parent = ngx_getppid();

获取当前进程的进程ID( ngx_pid )和父进程的进程ID( ngx_parent )。

这在后续的进程管理中很有用。

在 src/os/unix/ngx_process.h 中:

#define ngx_getpid   getpid
#define ngx_getppid  getppid

getpidgetppid 是 C 语言中用于获取进程 ID 的函数,定义在 <unistd.h> 头文件中

getpid():获取当前进程的进程ID getppid():获取当前进程的父进程ID

父进程是创建当前进程的进程(如通过fork())。 若父进程终止,子进程的PPID会被重置为init进程(PID=1)


接下来是:

    log = ngx_log_init(ngx_prefix, ngx_error_log);
    if (log == NULL) {
        return 1;
    }

此次调用 ngx_log_init 时

prefix 和 error_log 都还没有设置此时还是 null

进入 ngx_log_init

首先是

ngx_log_t *
ngx_log_init(u_char *prefix, u_char *error_log)
{
    u_char  *p, *name;
    size_t   nlen, plen;

    ngx_log.file = &ngx_log_file;
    ngx_log.log_level = NGX_LOG_NOTICE;
  • 将全局日志对象 ngx_log 的文件指针指向 ngx_log_file

  • 设置默认日志级别为 NGX_LOG_NOTICE (通知级别)

    if (error_log == NULL) {
        error_log = (u_char *) NGX_ERROR_LOG_PATH;
    }

    name = error_log;
    nlen = ngx_strlen(name);

此时 error_log 还是null

于是进入这个 if 条件中

把默认值 NGX_ERROR_LOG_PATH 赋值给 error_log

这个默认值是在 执行 configure 命令时定义的一个宏,它的值由 configure 命令的配置项 –error-log-path 指定

    if (nlen == 0) {
        ngx_log_file.fd = ngx_stderr;
        return &ngx_log;
    }

    p = NULL;

nlen 不是0

跳过这个 if 条件

if (name[0] != '/') {

检查路径是否以 / 开头

是以 / 开头

所以当前 name 已经是绝对路径了,不需要拼接前缀

ngx_log_file.fd = ngx_open_file(name, NGX_FILE_APPEND,
                                    NGX_FILE_CREATE_OR_OPEN,
                                    NGX_FILE_DEFAULT_ACCESS);

以追加的方式打开 name 指向的 日志文件

此时返回的 fd 是 4

    if (ngx_log_file.fd == NGX_INVALID_FILE) {
        ngx_log_stderr(ngx_errno,
                       "[alert] could not open error log file: "
                       ngx_open_file_n " \"%s\" failed", name);

NGX_INVALID_FILE 的值是 -1 无效的文件描述符,表示上一步的打开文件失败

现在这个条件不成立,跳过这段代码

   if (p) {
        ngx_free(p);
    }

    return &ngx_log;

由于之前条件不成立,所以 没有用到 p

最后返回 ngx_log 的地址


回到 main 函数中

接下来是:

ngx_ssl_init(log);


接下来是:

  ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));

把 init_cycle 的每个字节都初始化为 0

    init_cycle.log = log;

将之前 初始化的 日志对象的地址 记录在 log 字段

    ngx_cycle = &init_cycle;

现在 ngx_cycle 是指向 init_cycle 的指针了


   init_cycle.pool = ngx_create_pool(1024, log);

创建一个内存池要求的内存大小是 1024 字节,然后将地址记录到 init_cycle 的 pool 字段进行管理

进入 ngx_create_pool

ngx_pool_t *
ngx_create_pool(size_t size, ngx_log_t *log)
{
    ngx_pool_t  *p;

    p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);
    if (p == NULL) {
        return NULL;
    }

使用 ngx_memalign 来分配内存

NGX_POOL_ALIGNMENT 是要求的对齐边界,值为 16

进入 ngx_memalign

void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
    void  *p;
    int    err;

    err = posix_memalign(&p, alignment, size);

调用 posix_memalign 来分配一块对齐的内存

此次返回值为 0

也就是分配内存成功了

p=0x5aa55f9765a0

这个地址是按 16 对齐的

if (err) {
        ngx_log_error(NGX_LOG_EMERG, log, err,
                      "posix_memalign(%uz, %uz) failed", alignment, size);
        p = NULL;
    }

条件不成立,跳过这段代码

return p;

把分配的地址返回到

ngx_create_pool 函数中


回到 ngx_create_pool

接下来是:

   if (p == NULL) {
        return NULL;
    }

条件不成立,跳过这段代码

    p->d.last = (u_char *) p + sizeof(ngx_pool_t);
    p->d.end = (u_char *) p + size;
    p->d.next = NULL;
    p->d.failed = 0;

    size = size - sizeof(ngx_pool_t);
    p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;

    p->current = p;
    p->chain = NULL;
    p->large = NULL;
    p->cleanup = NULL;
    p->log = log;

    return p;

赋值然后返回 内存池 地址

当前 size = 944 , NGX_MAX_ALLOC_FROM_POOL = -1 所以 p->max=944


回到 main 函数中

接下来是:

   if (init_cycle.pool == NULL) {
        return 1;
    }

条件不成立,跳过这段代码

   if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
        return 1;
    }


    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }

进入 ngx_process_options

static ngx_int_t
ngx_process_options(ngx_cycle_t *cycle)
{
    u_char  *p;
    size_t   len;

    if (ngx_prefix) {

ngx_prefix 还是 null

所以跳过这个 if 代码段进入 else

接下来是:

ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);

将 默认的配置文件路径前缀设置给 cycle->conf_prefix

ngx_str_set(&cycle->prefix, NGX_PREFIX);

将 默认的路径前缀设置给 cycle->prefix

    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 在这里还是 null

进入 else 中,将 默认的配置文件路径设置给 cycle->conf_file 进行管理

接下来是:

    if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
        return NGX_ERROR;
    }

cycle->conf_file 保存的配置文件路径可能是 相对路径,需要 调用 ngx_conf_full_name 来拼接路径前缀 然后形成完成的路径

进入 ngx_conf_full_name 中

ngx_int_t
ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix)
{
    ngx_str_t  *prefix;

    prefix = conf_prefix ? &cycle->conf_prefix : &cycle->prefix;

    return ngx_get_full_name(cycle->pool, prefix, name);
}

这里传进来的 conf_prefix 的值是 0

所以 prefix =  &cycle->prefix; 选择 cycle->prefix (/usr/local/nginx/) 作为配置文件路径前缀

然后调用 ngx_get_full_name 来拼接路径

进入 ngx_get_full_name

ngx_int_t
ngx_get_full_name(ngx_pool_t *pool, ngx_str_t *prefix, ngx_str_t *name)
{
    size_t      len;
    u_char     *p, *n;
    ngx_int_t   rc;

    rc = ngx_test_full_name(name);

    if (rc == NGX_OK) {
        return rc;
    }

调用 ngx_test_full_name 来判断 name (/home/wsd/桌面/nginx/conf/nginx.conf) 是否是完整的路径

进入 ngx_test_full_name

static ngx_int_t
ngx_test_full_name(ngx_str_t *name)
{
#if (NGX_WIN32)
    u_char  c0, c1;

    c0 = name->data[0];

    if (name->len < 2) {
        if (c0 == '/') {
            return 2;
        }

        return NGX_DECLINED;
    }

    c1 = name->data[1];

    if (c1 == ':') {
        c0 |= 0x20;

        if ((c0 >= 'a' && c0 <= 'z')) {
            return NGX_OK;
        }

        return NGX_DECLINED;
    }

    if (c1 == '/') {
        return NGX_OK;
    }

    if (c0 == '/') {
        return 2;
    }

    return NGX_DECLINED;

#else

    if (name->data[0] == '/') {
        return NGX_OK;
    }

    return NGX_DECLINED;

#endif
}

当前环境是 Ubuntu #if (NGX_WIN32) 不成立

所以接下来执行的是:

    if (name->data[0] == '/') {
        return NGX_OK;
    }

    return NGX_DECLINED;

条件成立 name 的第一个字符是 /

被认为是 绝对路径

返回 NGX_OK


回到 ngx_get_full_name

   rc = ngx_test_full_name(name);

    if (rc == NGX_OK) {
        return rc;
    }

rc 得到的返回值是 NGX_OK

条件成立,把这个 NGX_OK 返回到 ngx_conf_full_name

return ngx_get_full_name(cycle->pool, prefix, name);

这个结果继续向上返回到 ngx_process_options


回到 ngx_process_options

接下来是:

if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
        return NGX_ERROR;
    }

于是 这里 调用 ngx_conf_full_name 得到 返回值 NGX_OK

条件不成立

接下来是:

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

cycle->conf_file.data 是配置文件路径,

cycle->conf_file.data + cycle->conf_file.len - 1 指向这个路径字符串的最后一个字节

从最后一个字符向第一个字符遍历

if (ngx_path_separator(*p)) { 判断当前这个字符是否是分隔符 /

这个 分隔符后面是 配置文件的文件名,前面是配置文件的目录

将 cycle->conf_file.data 的地址赋给 cycle->conf_prefix.data

从这个地址开始 len 个字符是 配置文件所在的目录

于是

cycle->conf_file.data(0x5bfbfeaf3e50) = cycle->conf_prefix.data(0x5bfbfeaf3e50)

这2个地址一样

cycle->conf_file.len=38 cycle->conf_file.data=/home/wsd/桌面/nginx/conf/nginx.conf cycle->conf_prefix.len=28 cycle->conf_prefix.data=/home/wsd/桌面/nginx/conf/

就是 cycle->conf_file.data 的前 28 个字节

接下来是:

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=null 还没有设置它

所以进入 else

把 默认值 NGX_ERROR_LOG_PATH(/home/wsd/桌面/nginx/LOG/error.log)

设置给 cycle->error_log

接下来是:

    if (ngx_conf_params) {
        cycle->conf_param.len = ngx_strlen(ngx_conf_params);
        cycle->conf_param.data = ngx_conf_params;
    }

ngx_conf_params 没有设置是 null

所以跳过这段代码

if (ngx_test_config) {
        cycle->log->log_level = NGX_LOG_INFO;
    }

ngx_test_config 是 0

所以跳过这段代码

  return NGX_OK;

返回结果


回到 main 函数中

接下来是:

   if (ngx_os_init(log) != NGX_OK) {
        return 1;
    }

进入 ngx_os_init

ngx_int_t
ngx_os_init(ngx_log_t *log)
{
    ngx_time_t  *tp;
    ngx_uint_t   n;
#if (NGX_HAVE_LEVEL1_DCACHE_LINESIZE)
    long         size;
#endif

#if (NGX_HAVE_OS_SPECIFIC_INIT)
    if (ngx_os_specific_init(log) != NGX_OK) {
        return NGX_ERROR;
    }
#endif

调用 ngx_os_specific_init 函数

进入 ngx_os_specific_init

ngx_int_t
ngx_os_specific_init(ngx_log_t *log)
{
    struct utsname  u;

    if (uname(&u) == -1) {
        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "uname() failed");
        return NGX_ERROR;
    }

调用 uname 获取系统信息

这次获得的系统信息如下:

// 操作系统名称

u.sysname=Linux

//主机名 u.nodename=wsd-vm

//操作系统发行版本 u.release=6.8.0-52-generic

// 操作系统版本信息 u.version=#53~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Jan 15 19:18:46 UTC 2

// 硬件架构 u.machine=x86_64

接下来是:

    (void) ngx_cpystrn(ngx_linux_kern_ostype, (u_char *) u.sysname,
                       sizeof(ngx_linux_kern_ostype));

    (void) ngx_cpystrn(ngx_linux_kern_osrelease, (u_char *) u.release,
                       sizeof(ngx_linux_kern_osrelease));

复制 u.sysname 和 u.release 存储到全局变量 ngx_linux_kern_ostype 和 ngx_linux_kern_osrelease

   ngx_os_io = ngx_linux_io;

    return NGX_OK;

设置 ngx_os_io

然后返回结果


回到 ngx_os_init

接下来是:

   if (ngx_init_setproctitle(log) != NGX_OK) {
        return NGX_ERROR;
    }

调用 ngx_init_setproctitle

进入 ngx_init_setproctitle

ngx_int_t
ngx_init_setproctitle(ngx_log_t *log)
{
    u_char      *p;
    size_t       size;
    ngx_uint_t   i;

    size = 0;

    for (i = 0; environ[i]; i++) {
        size += ngx_strlen(environ[i]) + 1;
    }

遍历 环境变量

ngx_strlen(environ[i]) + 1;

是当前这个环境变量占用的内存字节数量(字符串长度 + 字符串结束标志 ‘\0’)

累加到 size 中,最终 size 的值是整个环境变量占据的字节数量

这次的执行情况:

i=0 environ[0]=“COLORTERM=truecolor” ngx_strlen(environ[0]) + 1  =20 size=20

i=1 environ[1]=“LANGUAGE=zh_CN:en” ngx_strlen(environ[1]) + 1  =18 size=38

i=2 environ[2]=“LC_ADDRESS=zh_CN.UTF-8” ngx_strlen(environ[2]) + 1  =23 size=61

i=3 environ[3]=“LC_NAME=zh_CN.UTF-8” ngx_strlen(environ[3]) + 1  =20 size=81

i=4 environ[4]=“LC_MONETARY=zh_CN.UTF-8” ngx_strlen(environ[4]) + 1  =24 size=105

i=5 environ[5]=“XAUTHORITY=/run/user/1000/.mutter-Xwaylandauth.SUZ122” ngx_strlen(environ[5]) + 1  =54 size=159

i=6 environ[6]=“LC_PAPER=zh_CN.UTF-8” ngx_strlen(environ[6]) + 1  =21 size=180

i=7 environ[7]=“LANG=zh_CN.UTF-8” ngx_strlen(environ[7]) + 1  =17 size=197

i=8 environ[8]=“LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:.tar=01;31:.tgz=01;31:.arc=01;31:.arj=01;31:.taz=01;31:.lha=01;31:.lz4=01;31:.lzh=01;31:.lzma=01;31:.tlz=01;31:.txz=01;31:.tzo=01;31:.t7z=01;31:.zip=01;31:.z=01;31:.dz=01;31:.gz=01;31:.lrz=01;31:.lz=01;31:.lzo=01;31:.xz=01;31:.zst=01;31:.tzst=01;31:.bz2=01;31:.bz=01;31:.tbz=01;31:.tbz2=01;31:.tz=01;31:.deb=01;31:.rpm=01;31:.jar=01;31:.war=01;31:.ear=01;31:.sar=01;31:.rar=01;31:.alz=01;31:.ace=01;31:.zoo=01;31:.cpio=01;31:.7z=01;31:.rz=01;31:.cab=01;31:.wim=01;31:.swm=01;31:.dwm=01;31:.esd=01;31:.jpg=01;35:.jpeg=01;35:.mjpg=01;35:.mjpeg=01;35:.gif=01;35:.bmp=01;35:.pbm=01;35:.pgm=01;35:.ppm=01;35:.tga=01;35:.xbm=01;35:.xpm=01;35:.tif=01;35:.tiff=01;35:.png=01;35:.svg=01;35:.svgz=01;35:.mng=01;35:.pcx=01;35:.mov=01;35:.mpg=01;35:.mpeg=01;35:.m2v=01;35:.mkv=01;35:.webm=01;35:.webp=01;35:.ogm=01;35:.mp4=01;35:.m4v=01;35:.mp4v=01;35:.vob=01;35:.qt=01;35:.nuv=01;35:.wmv=01;35:.asf=01;35:.rm=01;35:.rmvb=01;35:.flc=01;35:.avi=01;35:.fli=01;35:.flv=01;35:.gl=01;35:.dl=01;35:.xcf=01;35:.xwd=01;35:.yuv=01;35:.cgm=01;35:.emf=01;35:.ogv=01;35:.ogx=01;35:.aac=00;36:.au=00;36:.flac=00;36:.m4a=00;36:.mid=00;36:.midi=00;36:.mka=00;36:.mp3=00;36:.mpc=00;36:.ogg=00;36:.ra=00;36:.wav=00;36:.oga=00;36:.opus=00;36:.spx=00;36:.xspf=00;36:” ngx_strlen(environ[8]) + 1  =1519 size=1716

i=9 environ[9]=“XDG_CURRENT_DESKTOP=ubuntu:GNOME” ngx_strlen(environ[9]) + 1  =33 size=1749

i=10 environ[10]=“TERM=xterm-256color” ngx_strlen(environ[10]) + 1  =20 size=1769

i=11 environ[11]=“LC_IDENTIFICATION=zh_CN.UTF-8” ngx_strlen(environ[11]) + 1  =30 size=1799

i=12 environ[12]=“DISPLAY=:0” ngx_strlen(environ[12]) + 1  =11 size=1810

i=13 environ[13]=“LC_TELEPHONE=zh_CN.UTF-8” ngx_strlen(environ[13]) + 1  =25 size=1835

i=14 environ[14]=“LC_MEASUREMENT=zh_CN.UTF-8” ngx_strlen(environ[14]) + 1  =27 size=1862

i=15 environ[15]=“LC_TIME=zh_CN.UTF-8” ngx_strlen(environ[15]) + 1  =20 size=1882

i=16 environ[16]=“PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin” ngx_strlen(environ[16]) + 1  =76 size=1958

i=17 environ[17]=“LC_NUMERIC=zh_CN.UTF-8” ngx_strlen(environ[17]) + 1  =23 size=1981

i=18 environ[18]=“MAIL=/var/mail/root” ngx_strlen(environ[18]) + 1  =20 size=2001

i=19 environ[19]=“LOGNAME=root” ngx_strlen(environ[19]) + 1  =13 size=2014

i=20 environ[20]=“USER=root” ngx_strlen(environ[20]) + 1  =10 size=2024

i=21 environ[21]=“HOME=/root” ngx_strlen(environ[21]) + 1  =11 size=2035

i=22 environ[22]=“SHELL=/bin/bash” ngx_strlen(environ[22]) + 1  =16 size=2051

i=23 environ[23]=“SUDO_COMMAND=./nginx” ngx_strlen(environ[23]) + 1  =21 size=2072

i=24 environ[24]=“SUDO_USER=wsd” ngx_strlen(environ[24]) + 1  =14 size=2086

i=25 environ[25]=“SUDO_UID=1000” ngx_strlen(environ[25]) + 1  =14 size=2100

i=26 environ[26]=“SUDO_GID=1000” ngx_strlen(environ[26]) + 1  =14 size=2114

接下来是:

   p = ngx_alloc(size, log);
    if (p == NULL) {
        return NGX_ERROR;
    }

为环境变量分配内存,环境变量将要迁移到新分配的内存中

此次运行的情况:

p = ngx_alloc(size=2114, log);

p=0x654273b10f20

接下来是:

    ngx_os_argv_last = ngx_os_argv[0];

ngx_os_argv_last 将用于标记命令行参数可用的边界

ngx_os_argv[0] 是存储参数的那片内存的首地址

接下来是:

for (i = 0; ngx_os_argv[i]; i++) {
        if (ngx_os_argv_last == ngx_os_argv[i]) {
            ngx_os_argv_last = ngx_os_argv[i] + ngx_strlen(ngx_os_argv[i]) + 1;
        }
    }

循环,每次循环获取下一个参数的首地址,直到这个地址为 null ,

null 是标记,意味着到此为止,后面没有更多的参数了

ngx_os_argv[i] 是参数首地址, ngx_strlen(ngx_os_argv[i]) 是参数的长度,最后再 + 1 ,就越过了这个参数的最后一个字节成了下一个参数的最后一个字节

所以下一次循环时 ngx_os_argv[i] 是下一个参数的首地址 等于 上一次循环被重新赋值的 ngx_os_argv_last

这样 ngx_os_argv_last 的值在不断的向后移动,直到它等于存贮参数的内存的最后一个字节的下一个字节(也是环境变量的第一个字节)

此次的执行情况是:

i=0 ngx_os_argv_last(0x7ffecc4747a6) == ngx_os_argv ngx_os_argv_last(0x7ffecc4747ae) = ngx_os_argv[0] + ngx_strlen(ngx_os_argv[0])(7) + 1;

因为此次运行时没有给命令行参数,所以 只有一个参数,也就是运行的程序名

接下来是:

for (i = 0; environ[i]; i++) {
        if (ngx_os_argv_last == environ[i]) {

            size = ngx_strlen(environ[i]) + 1;
            ngx_os_argv_last = environ[i] + size;

            ngx_cpystrn(p, (u_char *) environ[i], size);
            environ[i] = (char *) p;
            p += size;
        }
    }

现在 ngx_os_argv_last 等于环境变量的首地址

循环逻辑与上一个循环相同

ngx_os_argv_last 逐渐向后移

每次遍历还会将 环境变量依次迁移到新分配的内存

此次的运行情况:

i=0 ngx_os_argv_last(=0x7ffde3e967ae) == environ size(=20) = ngx_strlen(environ[0])(=19) + 1; ngx_os_argv_last(=0x7ffde3e967c2) = environ + size(=20); ngx_cpystrn(0x62a807451f20, 0x7ffde3e967ae, 20); environ = (char *) p(=0x62a807451f20); p(=0x62a807451f34) += size(=20);

i=1 ngx_os_argv_last(=0x7ffde3e967c2) == environ size(=18) = ngx_strlen(environ[1])(=17) + 1; ngx_os_argv_last(=0x7ffde3e967d4) = environ + size(=18); ngx_cpystrn(0x62a807451f34, 0x7ffde3e967c2, 18); environ = (char *) p(=0x62a807451f34); p(=0x62a807451f46) += size(=18);

i=2 ngx_os_argv_last(=0x7ffde3e967d4) == environ size(=23) = ngx_strlen(environ[2])(=22) + 1; ngx_os_argv_last(=0x7ffde3e967eb) = environ + size(=23); ngx_cpystrn(0x62a807451f46, 0x7ffde3e967d4, 23); environ = (char *) p(=0x62a807451f46); p(=0x62a807451f5d) += size(=23);

i=3 ngx_os_argv_last(=0x7ffde3e967eb) == environ size(=20) = ngx_strlen(environ[3])(=19) + 1; ngx_os_argv_last(=0x7ffde3e967ff) = environ + size(=20); ngx_cpystrn(0x62a807451f5d, 0x7ffde3e967eb, 20); environ = (char *) p(=0x62a807451f5d); p(=0x62a807451f71) += size(=20);

i=4 ngx_os_argv_last(=0x7ffde3e967ff) == environ size(=24) = ngx_strlen(environ[4])(=23) + 1; ngx_os_argv_last(=0x7ffde3e96817) = environ + size(=24); ngx_cpystrn(0x62a807451f71, 0x7ffde3e967ff, 24); environ = (char *) p(=0x62a807451f71); p(=0x62a807451f89) += size(=24);

i=5 ngx_os_argv_last(=0x7ffde3e96817) == environ size(=54) = ngx_strlen(environ[5])(=53) + 1; ngx_os_argv_last(=0x7ffde3e9684d) = environ + size(=54); ngx_cpystrn(0x62a807451f89, 0x7ffde3e96817, 54); environ = (char *) p(=0x62a807451f89); p(=0x62a807451fbf) += size(=54);

i=6 ngx_os_argv_last(=0x7ffde3e9684d) == environ size(=21) = ngx_strlen(environ[6])(=20) + 1; ngx_os_argv_last(=0x7ffde3e96862) = environ + size(=21); ngx_cpystrn(0x62a807451fbf, 0x7ffde3e9684d, 21); environ = (char *) p(=0x62a807451fbf); p(=0x62a807451fd4) += size(=21);

i=7 ngx_os_argv_last(=0x7ffde3e96862) == environ size(=17) = ngx_strlen(environ[7])(=16) + 1; ngx_os_argv_last(=0x7ffde3e96873) = environ + size(=17); ngx_cpystrn(0x62a807451fd4, 0x7ffde3e96862, 17); environ = (char *) p(=0x62a807451fd4); p(=0x62a807451fe5) += size(=17);

i=8 ngx_os_argv_last(=0x7ffde3e96873) == environ size(=1519) = ngx_strlen(environ[8])(=1518) + 1; ngx_os_argv_last(=0x7ffde3e96e62) = environ + size(=1519); ngx_cpystrn(0x62a807451fe5, 0x7ffde3e96873, 1519); environ = (char *) p(=0x62a807451fe5); p(=0x62a8074525d4) += size(=1519);

i=9 ngx_os_argv_last(=0x7ffde3e96e62) == environ size(=33) = ngx_strlen(environ[9])(=32) + 1; ngx_os_argv_last(=0x7ffde3e96e83) = environ + size(=33); ngx_cpystrn(0x62a8074525d4, 0x7ffde3e96e62, 33); environ = (char *) p(=0x62a8074525d4); p(=0x62a8074525f5) += size(=33);

i=10 ngx_os_argv_last(=0x7ffde3e96e83) == environ size(=20) = ngx_strlen(environ[10])(=19) + 1; ngx_os_argv_last(=0x7ffde3e96e97) = environ + size(=20); ngx_cpystrn(0x62a8074525f5, 0x7ffde3e96e83, 20); environ = (char *) p(=0x62a8074525f5); p(=0x62a807452609) += size(=20);

i=11 ngx_os_argv_last(=0x7ffde3e96e97) == environ size(=30) = ngx_strlen(environ[11])(=29) + 1; ngx_os_argv_last(=0x7ffde3e96eb5) = environ + size(=30); ngx_cpystrn(0x62a807452609, 0x7ffde3e96e97, 30); environ = (char *) p(=0x62a807452609); p(=0x62a807452627) += size(=30);

i=12 ngx_os_argv_last(=0x7ffde3e96eb5) == environ size(=11) = ngx_strlen(environ[12])(=10) + 1; ngx_os_argv_last(=0x7ffde3e96ec0) = environ + size(=11); ngx_cpystrn(0x62a807452627, 0x7ffde3e96eb5, 11); environ = (char *) p(=0x62a807452627); p(=0x62a807452632) += size(=11);

i=13 ngx_os_argv_last(=0x7ffde3e96ec0) == environ size(=25) = ngx_strlen(environ[13])(=24) + 1; ngx_os_argv_last(=0x7ffde3e96ed9) = environ + size(=25); ngx_cpystrn(0x62a807452632, 0x7ffde3e96ec0, 25); environ = (char *) p(=0x62a807452632); p(=0x62a80745264b) += size(=25);

i=14 ngx_os_argv_last(=0x7ffde3e96ed9) == environ size(=27) = ngx_strlen(environ[14])(=26) + 1; ngx_os_argv_last(=0x7ffde3e96ef4) = environ + size(=27); ngx_cpystrn(0x62a80745264b, 0x7ffde3e96ed9, 27); environ = (char *) p(=0x62a80745264b); p(=0x62a807452666) += size(=27);

i=15 ngx_os_argv_last(=0x7ffde3e96ef4) == environ size(=20) = ngx_strlen(environ[15])(=19) + 1; ngx_os_argv_last(=0x7ffde3e96f08) = environ + size(=20); ngx_cpystrn(0x62a807452666, 0x7ffde3e96ef4, 20); environ = (char *) p(=0x62a807452666); p(=0x62a80745267a) += size(=20);

i=16 ngx_os_argv_last(=0x7ffde3e96f08) == environ size(=76) = ngx_strlen(environ[16])(=75) + 1; ngx_os_argv_last(=0x7ffde3e96f54) = environ + size(=76); ngx_cpystrn(0x62a80745267a, 0x7ffde3e96f08, 76); environ = (char *) p(=0x62a80745267a); p(=0x62a8074526c6) += size(=76);

i=17 ngx_os_argv_last(=0x7ffde3e96f54) == environ size(=23) = ngx_strlen(environ[17])(=22) + 1; ngx_os_argv_last(=0x7ffde3e96f6b) = environ + size(=23); ngx_cpystrn(0x62a8074526c6, 0x7ffde3e96f54, 23); environ = (char *) p(=0x62a8074526c6); p(=0x62a8074526dd) += size(=23);

i=18 ngx_os_argv_last(=0x7ffde3e96f6b) == environ size(=20) = ngx_strlen(environ[18])(=19) + 1; ngx_os_argv_last(=0x7ffde3e96f7f) = environ + size(=20); ngx_cpystrn(0x62a8074526dd, 0x7ffde3e96f6b, 20); environ = (char *) p(=0x62a8074526dd); p(=0x62a8074526f1) += size(=20);

i=19 ngx_os_argv_last(=0x7ffde3e96f7f) == environ size(=13) = ngx_strlen(environ[19])(=12) + 1; ngx_os_argv_last(=0x7ffde3e96f8c) = environ + size(=13); ngx_cpystrn(0x62a8074526f1, 0x7ffde3e96f7f, 13); environ = (char *) p(=0x62a8074526f1); p(=0x62a8074526fe) += size(=13);

i=20 ngx_os_argv_last(=0x7ffde3e96f8c) == environ size(=10) = ngx_strlen(environ[20])(=9) + 1; ngx_os_argv_last(=0x7ffde3e96f96) = environ + size(=10); ngx_cpystrn(0x62a8074526fe, 0x7ffde3e96f8c, 10); environ = (char *) p(=0x62a8074526fe); p(=0x62a807452708) += size(=10);

i=21 ngx_os_argv_last(=0x7ffde3e96f96) == environ size(=11) = ngx_strlen(environ[21])(=10) + 1; ngx_os_argv_last(=0x7ffde3e96fa1) = environ + size(=11); ngx_cpystrn(0x62a807452708, 0x7ffde3e96f96, 11); environ = (char *) p(=0x62a807452708); p(=0x62a807452713) += size(=11);

i=22 ngx_os_argv_last(=0x7ffde3e96fa1) == environ size(=16) = ngx_strlen(environ[22])(=15) + 1; ngx_os_argv_last(=0x7ffde3e96fb1) = environ + size(=16); ngx_cpystrn(0x62a807452713, 0x7ffde3e96fa1, 16); environ = (char *) p(=0x62a807452713); p(=0x62a807452723) += size(=16);

i=23 ngx_os_argv_last(=0x7ffde3e96fb1) == environ size(=21) = ngx_strlen(environ[23])(=20) + 1; ngx_os_argv_last(=0x7ffde3e96fc6) = environ + size(=21); ngx_cpystrn(0x62a807452723, 0x7ffde3e96fb1, 21); environ = (char *) p(=0x62a807452723); p(=0x62a807452738) += size(=21);

i=24 ngx_os_argv_last(=0x7ffde3e96fc6) == environ size(=14) = ngx_strlen(environ[24])(=13) + 1; ngx_os_argv_last(=0x7ffde3e96fd4) = environ + size(=14); ngx_cpystrn(0x62a807452738, 0x7ffde3e96fc6, 14); environ = (char *) p(=0x62a807452738); p(=0x62a807452746) += size(=14);

i=25 ngx_os_argv_last(=0x7ffde3e96fd4) == environ size(=14) = ngx_strlen(environ[25])(=13) + 1; ngx_os_argv_last(=0x7ffde3e96fe2) = environ + size(=14); ngx_cpystrn(0x62a807452746, 0x7ffde3e96fd4, 14); environ = (char *) p(=0x62a807452746); p(=0x62a807452754) += size(=14);

i=26 ngx_os_argv_last(=0x7ffde3e96fe2) == environ size(=14) = ngx_strlen(environ[26])(=13) + 1; ngx_os_argv_last(=0x7ffde3e96ff0) = environ + size(=14); ngx_cpystrn(0x62a807452754, 0x7ffde3e96fe2, 14); environ = (char *) p(=0x62a807452754); p(=0x62a807452762) += size(=14);

接下来是:

ngx_os_argv_last--;

    return NGX_OK;

ngx_os_argv_last 的值 -1, 指向原来存放环境变量的那片内存的最后一个字节

然后返回


回到 ngx_os_init

接下来是:

ngx_pagesize = getpagesize();

获取 当前系统一页的大小是多少字节

此次的情况

ngx_pagesize=4096

   ngx_cacheline_size = NGX_CPU_CACHE_LINE;

存储 CPU 缓存行大小,默认值为 NGX_CPU_CACHE_LINE

目前的情况:

ngx_cacheline_size=64

for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }

计算页面大小的对数( ngx_pagesize_shift ),即页面大小是 2 的多少次幂。

例如,4KB 的页面大小对应 ngx_pagesize_shift = 12

此次的情况:

ngx_pagesize_shift=12

  if (ngx_ncpu == 0) {
        ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN);
    }

获取当前系统在线的 CPU 核心数

此次的情况是:

ngx_ncpu=2

    if (ngx_ncpu < 1) {
        ngx_ncpu = 1;
    }

条件不成立,跳过这段代码

    size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
    if (size > 0) {
        ngx_cacheline_size = size;
    }

sysconf(_SC_LEVEL1_DCACHE_LINESIZE) :获取一级缓存行大小

成功就更新 ngx_cacheline_size ,之前的值是默认值

此次的情况:

获取成功,但获得的值和默认值一样

ngx_cacheline_size=64

接下来是:

    ngx_cpuinfo();

接下来是:

    if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
        ngx_log_error(NGX_LOG_ALERT, log, errno,
                      "getrlimit(RLIMIT_NOFILE) failed");
        return NGX_ERROR;
    }

    ngx_max_sockets = (ngx_int_t) rlmt.rlim_cur;

获取文件描述符数量的限制

此次的情况是:

ngx_max_sockets=1024

#if (NGX_HAVE_INHERITED_NONBLOCK || NGX_HAVE_ACCEPT4)
    ngx_inherited_nonblocking = 1;
#else
    ngx_inherited_nonblocking = 0;
#endif

ngx_inherited_nonblocking :全局变量,指示当前环境是否支持继承非阻塞套接字

当前情况:

ngx_inherited_nonblocking=1

   tp = ngx_timeofday();
    srandom(((unsigned) ngx_pid << 16) ^ tp->sec ^ tp->msec);

    return NGX_OK;

获取当前的时间缓存 用来 设置随机数种子

返回 NGX_OK


回到 main 函数中

接下来是:

    if (ngx_crc32_table_init() != NGX_OK) {
        return 1;
    }

   ngx_slab_sizes_init();

进入 ngx_slab_sizes_init

void
ngx_slab_sizes_init(void)
{
    ngx_uint_t  n;

    ngx_slab_max_size = ngx_pagesize / 2;
    ngx_slab_exact_size = ngx_pagesize / (8 * sizeof(uintptr_t));
    for (n = ngx_slab_exact_size; n >>= 1; ngx_slab_exact_shift++) {
        /* void */
    }
}

此次的情况是:

ngx_slab_max_size=2048 ngx_slab_exact_size=64 ngx_slab_exact_shift=6


回到 main 函数中

接下来是:

   if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }

进入 ngx_add_inherited_sockets

static ngx_int_t
ngx_add_inherited_sockets(ngx_cycle_t *cycle)
{
    u_char           *p, *v, *inherited;
    ngx_int_t         s;
    ngx_listening_t  *ls;

    inherited = (u_char *) getenv(NGINX_VAR);

此次

inherited 是 null,没有需要继承的 套接字描述符

    if (inherited == NULL) {
        return NGX_OK;
    }

返回 NGX_OK


回到 main 函数中

接下来是:

    if (ngx_preinit_modules() != NGX_OK) {
        return 1;
    }

进入 ngx_preinit_modules

ngx_int_t
ngx_preinit_modules(void)
{
    ngx_uint_t  i;

    for (i = 0; ngx_modules[i]; i++) {
        ngx_modules[i]->index = i;
        ngx_modules[i]->name = ngx_module_names[i];
    }

    ngx_modules_n = i;
    ngx_max_module = ngx_modules_n + NGX_MAX_DYNAMIC_MODULES;

    return NGX_OK;
}

进入循环,遍历 ngx_modules 数组

为每个模块的 index 和 name 字段赋值

此次的情况是:

ngx_modules[0]->index = 0 ngx_modules[0]->name = ngx_core_module ngx_modules[1]->index = 1 ngx_modules[1]->name = ngx_errlog_module ngx_modules[2]->index = 2 ngx_modules[2]->name = ngx_conf_module ngx_modules[3]->index = 3 ngx_modules[3]->name = ngx_openssl_module ngx_modules[4]->index = 4 ngx_modules[4]->name = ngx_regex_module ngx_modules[5]->index = 5 ngx_modules[5]->name = ngx_events_module ngx_modules[6]->index = 6 ngx_modules[6]->name = ngx_event_core_module ngx_modules[7]->index = 7 ngx_modules[7]->name = ngx_epoll_module ngx_modules[8]->index = 8 ngx_modules[8]->name = ngx_http_module ngx_modules[9]->index = 9 ngx_modules[9]->name = ngx_http_core_module ngx_modules[10]->index = 10 ngx_modules[10]->name = ngx_http_log_module ngx_modules[11]->index = 11 ngx_modules[11]->name = ngx_http_upstream_module ngx_modules[12]->index = 12 ngx_modules[12]->name = ngx_http_v2_module ngx_modules[13]->index = 13 ngx_modules[13]->name = ngx_http_static_module ngx_modules[14]->index = 14 ngx_modules[14]->name = ngx_http_gzip_static_module ngx_modules[15]->index = 15 ngx_modules[15]->name = ngx_http_autoindex_module ngx_modules[16]->index = 16 ngx_modules[16]->name = ngx_http_index_module ngx_modules[17]->index = 17 ngx_modules[17]->name = ngx_http_mirror_module ngx_modules[18]->index = 18 ngx_modules[18]->name = ngx_http_try_files_module ngx_modules[19]->index = 19 ngx_modules[19]->name = ngx_http_auth_basic_module ngx_modules[20]->index = 20 ngx_modules[20]->name = ngx_http_access_module ngx_modules[21]->index = 21 ngx_modules[21]->name = ngx_http_limit_conn_module ngx_modules[22]->index = 22 ngx_modules[22]->name = ngx_http_limit_req_module ngx_modules[23]->index = 23 ngx_modules[23]->name = ngx_http_geo_module ngx_modules[24]->index = 24 ngx_modules[24]->name = ngx_http_map_module ngx_modules[25]->index = 25 ngx_modules[25]->name = ngx_http_split_clients_module ngx_modules[26]->index = 26 ngx_modules[26]->name = ngx_http_referer_module ngx_modules[27]->index = 27 ngx_modules[27]->name = ngx_http_rewrite_module ngx_modules[28]->index = 28 ngx_modules[28]->name = ngx_http_ssl_module ngx_modules[29]->index = 29 ngx_modules[29]->name = ngx_http_proxy_module ngx_modules[30]->index = 30 ngx_modules[30]->name = ngx_http_fastcgi_module ngx_modules[31]->index = 31 ngx_modules[31]->name = ngx_http_uwsgi_module ngx_modules[32]->index = 32 ngx_modules[32]->name = ngx_http_scgi_module ngx_modules[33]->index = 33 ngx_modules[33]->name = ngx_http_grpc_module ngx_modules[34]->index = 34 ngx_modules[34]->name = ngx_http_memcached_module ngx_modules[35]->index = 35 ngx_modules[35]->name = ngx_http_empty_gif_module ngx_modules[36]->index = 36 ngx_modules[36]->name = ngx_http_browser_module ngx_modules[37]->index = 37 ngx_modules[37]->name = ngx_http_upstream_hash_module ngx_modules[38]->index = 38 ngx_modules[38]->name = ngx_http_upstream_ip_hash_module ngx_modules[39]->index = 39 ngx_modules[39]->name = ngx_http_upstream_least_conn_module ngx_modules[40]->index = 40 ngx_modules[40]->name = ngx_http_upstream_random_module ngx_modules[41]->index = 41 ngx_modules[41]->name = ngx_http_upstream_keepalive_module ngx_modules[42]->index = 42 ngx_modules[42]->name = ngx_http_upstream_zone_module ngx_modules[43]->index = 43 ngx_modules[43]->name = ngx_http_write_filter_module ngx_modules[44]->index = 44 ngx_modules[44]->name = ngx_http_header_filter_module ngx_modules[45]->index = 45 ngx_modules[45]->name = ngx_http_chunked_filter_module ngx_modules[46]->index = 46 ngx_modules[46]->name = ngx_http_v2_filter_module ngx_modules[47]->index = 47 ngx_modules[47]->name = ngx_http_range_header_filter_module ngx_modules[48]->index = 48 ngx_modules[48]->name = ngx_http_gzip_filter_module ngx_modules[49]->index = 49 ngx_modules[49]->name = ngx_http_postpone_filter_module ngx_modules[50]->index = 50 ngx_modules[50]->name = ngx_http_ssi_filter_module ngx_modules[51]->index = 51 ngx_modules[51]->name = ngx_http_charset_filter_module ngx_modules[52]->index = 52 ngx_modules[52]->name = ngx_http_userid_filter_module ngx_modules[53]->index = 53 ngx_modules[53]->name = ngx_http_headers_filter_module ngx_modules[54]->index = 54 ngx_modules[54]->name = ngx_http_copy_filter_module ngx_modules[55]->index = 55 ngx_modules[55]->name = ngx_http_range_body_filter_module ngx_modules[56]->index = 56 ngx_modules[56]->name = ngx_http_not_modified_filter_module ngx_modules[57]->index = 57 ngx_modules[57]->name = ngx_stream_module ngx_modules[58]->index = 58 ngx_modules[58]->name = ngx_stream_core_module ngx_modules[59]->index = 59 ngx_modules[59]->name = ngx_stream_log_module ngx_modules[60]->index = 60 ngx_modules[60]->name = ngx_stream_proxy_module ngx_modules[61]->index = 61 ngx_modules[61]->name = ngx_stream_upstream_module ngx_modules[62]->index = 62 ngx_modules[62]->name = ngx_stream_write_filter_module ngx_modules[63]->index = 63 ngx_modules[63]->name = ngx_stream_ssl_module ngx_modules[64]->index = 64 ngx_modules[64]->name = ngx_stream_limit_conn_module ngx_modules[65]->index = 65 ngx_modules[65]->name = ngx_stream_access_module ngx_modules[66]->index = 66 ngx_modules[66]->name = ngx_stream_geo_module ngx_modules[67]->index = 67 ngx_modules[67]->name = ngx_stream_map_module ngx_modules[68]->index = 68 ngx_modules[68]->name = ngx_stream_split_clients_module ngx_modules[69]->index = 69 ngx_modules[69]->name = ngx_stream_return_module ngx_modules[70]->index = 70 ngx_modules[70]->name = ngx_stream_set_module ngx_modules[71]->index = 71 ngx_modules[71]->name = ngx_stream_upstream_hash_module ngx_modules[72]->index = 72 ngx_modules[72]->name = ngx_stream_upstream_least_conn_module ngx_modules[73]->index = 73 ngx_modules[73]->name = ngx_stream_upstream_random_module ngx_modules[74]->index = 74 ngx_modules[74]->name = ngx_stream_upstream_zone_module

ngx_modules_n 静态模块的总数

ngx_max_module 表示Nginx支持的最大模块数量

NGX_MAX_DYNAMIC_MODULES 动态加载模块的最大数量

ngx_modules_n=75 ngx_max_module(=203) = ngx_modules_n(75) + NGX_MAX_DYNAMIC_MODULES(128)


回到 main 函数中

接下来是:

cycle = ngx_init_cycle(&init_cycle);
    if (cycle == NULL) {
        if (ngx_test_config) {
            ngx_log_stderr(0, "configuration file %s test failed",
                           init_cycle.conf_file.data);
        }

        return 1;
    }

调用 ngx_init_cycle

进入 ngx_init_cycle

ngx_cycle_t *
ngx_init_cycle(ngx_cycle_t *old_cycle)
{
    void                *rv;
    char               **senv;
    ngx_uint_t           i, n;
    ngx_log_t           *log;
    ngx_time_t          *tp;
    ngx_conf_t           conf;
    ngx_pool_t          *pool;
    ngx_cycle_t         *cycle, **old;
    ngx_shm_zone_t      *shm_zone, *oshm_zone;
    ngx_list_part_t     *part, *opart;
    ngx_open_file_t     *file;
    ngx_listening_t     *ls, *nls;
    ngx_core_conf_t     *ccf, *old_ccf;
    ngx_core_module_t   *module;
    char                 hostname[NGX_MAXHOSTNAMELEN];

    ngx_timezone_update();

    /* force localtime update with a new timezone */

    tp = ngx_timeofday();
    tp->sec = 0;

    ngx_time_update();

更新时间

   log = old_cycle->log;

获取之前的 log 对象,暂时还是用它来记录 log

   pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
    if (pool == NULL) {
        return NULL;
    }
    pool->log = log;

创建一个新的内存池,然后设置它使用的 log

此次的情况是:

pool = ngx_create_pool(16384, log) pool= 0x5f33e4db67b0 (地址)

接下来是:

   cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
    if (cycle == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

此次的情况是:

cycle = ngx_pcalloc(pool, 648); cycle= 0x5c67408e7800

    cycle->pool = pool;
    cycle->log = log;
    cycle->old_cycle = old_cycle;
   cycle->conf_prefix.len = old_cycle->conf_prefix.len;
    cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix);
    if (cycle->conf_prefix.data == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

给字段赋值

此次的情况是:

cycle->conf_prefix.len =28 cycle->conf_prefix.data=/home/wsd/桌面/nginx/conf/

    cycle->prefix.len = old_cycle->prefix.len;
    cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix);
    if (cycle->prefix.data == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

此次的情况是:

cycle->prefix.len = 17) cycle->prefix.data= /usr/local/nginx/

    cycle->error_log.len = old_cycle->error_log.len;
    cycle->error_log.data = ngx_pnalloc(pool, old_cycle->error_log.len + 1);
    if (cycle->error_log.data == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }
    ngx_cpystrn(cycle->error_log.data, old_cycle->error_log.data,
                old_cycle->error_log.len + 1);

此次的情况是:

cycle->error_log.len=36

cycle->error_log.data=/home/wsd/桌面/nginx/LOG/error.log

   cycle->conf_file.len = old_cycle->conf_file.len;
    cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1);
    if (cycle->conf_file.data == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }
    ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data,
                old_cycle->conf_file.len + 1);

此次的情况是:

cycle->conf_file.len=38 cycle->conf_file.data=/home/wsd/桌面/nginx/conf/nginx.conf

    cycle->conf_param.len = old_cycle->conf_param.len;
    cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param);
    if (cycle->conf_param.data == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

此次的情况是:

cycle->conf_param.len=0 cycle->conf_param.data 是 null

运行时没有给命令行参数

    n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10;

此次的情况是:

n = 0 ? 0 : 10; n=10

    if (ngx_array_init(&cycle->paths, pool, n, sizeof(ngx_path_t *))
        != NGX_OK)
    {
        ngx_destroy_pool(pool);
        return NULL;
    }

    ngx_memzero(cycle->paths.elts, n * sizeof(ngx_path_t *));

paths 数组的前 n 个元素清零

    if (ngx_array_init(&cycle->config_dump, pool, 1, sizeof(ngx_conf_dump_t))
        != NGX_OK)
    {
        ngx_destroy_pool(pool);
        return NULL;
    }

初始化数组 config_dump

    ngx_rbtree_init(&cycle->config_dump_rbtree, &cycle->config_dump_sentinel,
                    ngx_str_rbtree_insert_value);

   if (old_cycle->open_files.part.nelts) {
        n = old_cycle->open_files.part.nelts;
        for (part = old_cycle->open_files.part.next; part; part = part->next) {
            n += part->nelts;
        }

    } else {
        n = 20;
    }

此次运行的情况是:

old_cycle->open_files.part.nelts=0

所以进入 else n=20

if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
        != NGX_OK)
    {
        ngx_destroy_pool(pool);
        return NULL;
    }

初始化新周期的 open_files 列表。

此次运行的情况是:

ngx_list_init(&cycle->open_files, pool, n =20 , sizeof(ngx_open_file_t) =40 )

    if (old_cycle->shared_memory.part.nelts) {
        n = old_cycle->shared_memory.part.nelts;
        for (part = old_cycle->shared_memory.part.next; part; part = part->next)
        {
            n += part->nelts;
        }

    } else {
        n = 1;
    }

设置新周期的 shared_memory 的元素数量

此次运行的情况是:

old_cycle->shared_memory.part.nelts=0

所以 进入else n=1

  if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))
        != NGX_OK)
    {
        ngx_destroy_pool(pool);
        return NULL;
    }

初始化 shared_memory

此次运行的情况是:

ngx_list_init(&cycle->shared_memory, pool, n =1 , sizeof(ngx_shm_zone_t) =88 )

   n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;

此次运行的情况是:

n( =10 ) = old_cycle->listening.nelts( =0 ) ? old_cycle->listening.nelts( =0 ) : 10

  if (ngx_array_init(&cycle->listening, pool, n, sizeof(ngx_listening_t))
        != NGX_OK)
    {
        ngx_destroy_pool(pool);
        return NULL;
    }

初始化 cycle->listening 数组

此次运行的情况是:

ngx_array_init(&cycle->listening, pool, n( =10 ), sizeof(ngx_listening_t)( =296 ))

    ngx_memzero(cycle->listening.elts, n * sizeof(ngx_listening_t));

cycle->listening 内存区域清 0

   ngx_queue_init(&cycle->reusable_connections_queue);
    cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
    if (cycle->conf_ctx == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

从内存池 pool 中分配一个指针数组 conf_ctx ,每个元素对应一个模块的配置结构指针。


    if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed");
        ngx_destroy_pool(pool);
        return NULL;
    }

调用 gethostname() 系统调用获取本地主机名,存储到 hostname 缓冲区。

    hostname[NGX_MAXHOSTNAMELEN - 1] = '\0';
    cycle->hostname.len = ngx_strlen(hostname);

确保 hostname\0 结尾

计算主机名的实际长度(不含终止符),存储到 cycle->hostname.len

    cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len);
    if (cycle->hostname.data == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

从内存池 pool 分配内存,存储主机名的副本

    ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);

将主机名转换为全小写,存储到 cycle->hostname.data

此次运行的情况是:

hostname=wsd-vm cycle->hostname.len=6 cycle->hostname.data = ngx_pnalloc(pool, 6) cycle->hostname.data=0x6165d5b590d0 地址 cycle->hostname.data = wsd-vm

    if (ngx_cycle_modules(cycle) != NGX_OK) {
        ngx_destroy_pool(pool);
        return NULL;
    }

调用 ngx_cycle_modules 初始化 cycle->modules 数组,该数组包含所有核心模块的指针


    for (i = 0; cycle->modules[i]; i++) {
        if (cycle->modules[i]->type != NGX_CORE_MODULE) {
            continue;
        }

遍历所有核心模块

module = cycle->modules[i]->ctx;

获取核心模块的配置

if (module->create_conf) {
            rv = module->create_conf(cycle);
            if (rv == NULL) {
                ngx_destroy_pool(pool);
                return NULL;
            }
            cycle->conf_ctx[cycle->modules[i]->index] = rv;
        }
    }

调用模块的 create_conf 方法创建默认配置结构,并将其存储到 conf_ctx 数组的对应位置。

此次运行的情况是:

i=0 cycle->modules[0]->name = ngx_core_module cycle->modules[0]->type == NGX_CORE_MODULE module->create_conf = 0x5c9ee022c9b8 cycle->conf_ctx[0] = 0x5c9f13b4c738

i=1 cycle->modules[1]->name = ngx_errlog_module cycle->modules[1]->type == NGX_CORE_MODULE module->create_conf = (nil)

i=2 cycle->modules[2]->name = ngx_conf_module cycle->modules[2]->type != NGX_CORE_MODULE continue

i=3 cycle->modules[3]->name = ngx_openssl_module cycle->modules[3]->type == NGX_CORE_MODULE module->create_conf = 0x5c9ee02587ea cycle->conf_ctx[3] = 0x5c9f13b4c830

i=4 cycle->modules[4]->name = ngx_regex_module cycle->modules[4]->type == NGX_CORE_MODULE module->create_conf = 0x5c9ee0263174 cycle->conf_ctx[4] = 0x5c9f13b4c838

i=5 cycle->modules[5]->name = ngx_events_module cycle->modules[5]->type == NGX_CORE_MODULE module->create_conf = (nil)

i=6 cycle->modules[6]->name = ngx_event_core_module cycle->modules[6]->type != NGX_CORE_MODULE continue

i=7 cycle->modules[7]->name = ngx_epoll_module cycle->modules[7]->type != NGX_CORE_MODULE continue

i=8 cycle->modules[8]->name = ngx_http_module cycle->modules[8]->type == NGX_CORE_MODULE module->create_conf = (nil)

i=9 cycle->modules[9]->name = ngx_http_core_module cycle->modules[9]->type != NGX_CORE_MODULE continue

i=10 cycle->modules[10]->name = ngx_http_log_module cycle->modules[10]->type != NGX_CORE_MODULE continue

i=11 cycle->modules[11]->name = ngx_http_upstream_module cycle->modules[11]->type != NGX_CORE_MODULE continue

i=12 cycle->modules[12]->name = ngx_http_v2_module cycle->modules[12]->type != NGX_CORE_MODULE continue

i=13 cycle->modules[13]->name = ngx_http_static_module cycle->modules[13]->type != NGX_CORE_MODULE continue

i=14 cycle->modules[14]->name = ngx_http_gzip_static_module cycle->modules[14]->type != NGX_CORE_MODULE continue

i=15 cycle->modules[15]->name = ngx_http_autoindex_module cycle->modules[15]->type != NGX_CORE_MODULE continue

i=16 cycle->modules[16]->name = ngx_http_index_module cycle->modules[16]->type != NGX_CORE_MODULE continue

i=17 cycle->modules[17]->name = ngx_http_mirror_module cycle->modules[17]->type != NGX_CORE_MODULE continue

i=18 cycle->modules[18]->name = ngx_http_try_files_module cycle->modules[18]->type != NGX_CORE_MODULE continue

i=19 cycle->modules[19]->name = ngx_http_auth_basic_module cycle->modules[19]->type != NGX_CORE_MODULE continue

i=20 cycle->modules[20]->name = ngx_http_access_module cycle->modules[20]->type != NGX_CORE_MODULE continue

i=21 cycle->modules[21]->name = ngx_http_limit_conn_module cycle->modules[21]->type != NGX_CORE_MODULE continue

i=22 cycle->modules[22]->name = ngx_http_limit_req_module cycle->modules[22]->type != NGX_CORE_MODULE continue

i=23 cycle->modules[23]->name = ngx_http_geo_module cycle->modules[23]->type != NGX_CORE_MODULE continue

i=24 cycle->modules[24]->name = ngx_http_map_module cycle->modules[24]->type != NGX_CORE_MODULE continue

i=25 cycle->modules[25]->name = ngx_http_split_clients_module cycle->modules[25]->type != NGX_CORE_MODULE continue

i=26 cycle->modules[26]->name = ngx_http_referer_module cycle->modules[26]->type != NGX_CORE_MODULE continue

i=27 cycle->modules[27]->name = ngx_http_rewrite_module cycle->modules[27]->type != NGX_CORE_MODULE continue

i=28 cycle->modules[28]->name = ngx_http_ssl_module cycle->modules[28]->type != NGX_CORE_MODULE continue

i=29 cycle->modules[29]->name = ngx_http_proxy_module cycle->modules[29]->type != NGX_CORE_MODULE continue

i=30 cycle->modules[30]->name = ngx_http_fastcgi_module cycle->modules[30]->type != NGX_CORE_MODULE continue

i=31 cycle->modules[31]->name = ngx_http_uwsgi_module cycle->modules[31]->type != NGX_CORE_MODULE continue

i=32 cycle->modules[32]->name = ngx_http_scgi_module cycle->modules[32]->type != NGX_CORE_MODULE continue

i=33 cycle->modules[33]->name = ngx_http_grpc_module cycle->modules[33]->type != NGX_CORE_MODULE continue

i=34 cycle->modules[34]->name = ngx_http_memcached_module cycle->modules[34]->type != NGX_CORE_MODULE continue

i=35 cycle->modules[35]->name = ngx_http_empty_gif_module cycle->modules[35]->type != NGX_CORE_MODULE continue

i=36 cycle->modules[36]->name = ngx_http_browser_module cycle->modules[36]->type != NGX_CORE_MODULE continue

i=37 cycle->modules[37]->name = ngx_http_upstream_hash_module cycle->modules[37]->type != NGX_CORE_MODULE continue

i=38 cycle->modules[38]->name = ngx_http_upstream_ip_hash_module cycle->modules[38]->type != NGX_CORE_MODULE continue

i=39 cycle->modules[39]->name = ngx_http_upstream_least_conn_module cycle->modules[39]->type != NGX_CORE_MODULE continue

i=40 cycle->modules[40]->name = ngx_http_upstream_random_module cycle->modules[40]->type != NGX_CORE_MODULE continue

i=41 cycle->modules[41]->name = ngx_http_upstream_keepalive_module cycle->modules[41]->type != NGX_CORE_MODULE continue

i=42 cycle->modules[42]->name = ngx_http_upstream_zone_module cycle->modules[42]->type != NGX_CORE_MODULE continue

i=43 cycle->modules[43]->name = ngx_http_write_filter_module cycle->modules[43]->type != NGX_CORE_MODULE continue

i=44 cycle->modules[44]->name = ngx_http_header_filter_module cycle->modules[44]->type != NGX_CORE_MODULE continue

i=45 cycle->modules[45]->name = ngx_http_chunked_filter_module cycle->modules[45]->type != NGX_CORE_MODULE continue

i=46 cycle->modules[46]->name = ngx_http_v2_filter_module cycle->modules[46]->type != NGX_CORE_MODULE continue

i=47 cycle->modules[47]->name = ngx_http_range_header_filter_module cycle->modules[47]->type != NGX_CORE_MODULE continue

i=48 cycle->modules[48]->name = ngx_http_gzip_filter_module cycle->modules[48]->type != NGX_CORE_MODULE continue

i=49 cycle->modules[49]->name = ngx_http_postpone_filter_module cycle->modules[49]->type != NGX_CORE_MODULE continue

i=50 cycle->modules[50]->name = ngx_http_ssi_filter_module cycle->modules[50]->type != NGX_CORE_MODULE continue

i=51 cycle->modules[51]->name = ngx_http_charset_filter_module cycle->modules[51]->type != NGX_CORE_MODULE continue

i=52 cycle->modules[52]->name = ngx_http_userid_filter_module cycle->modules[52]->type != NGX_CORE_MODULE continue

i=53 cycle->modules[53]->name = ngx_http_headers_filter_module cycle->modules[53]->type != NGX_CORE_MODULE continue

i=54 cycle->modules[54]->name = ngx_http_copy_filter_module cycle->modules[54]->type != NGX_CORE_MODULE continue

i=55 cycle->modules[55]->name = ngx_http_range_body_filter_module cycle->modules[55]->type != NGX_CORE_MODULE continue

i=56 cycle->modules[56]->name = ngx_http_not_modified_filter_module cycle->modules[56]->type != NGX_CORE_MODULE continue

i=57 cycle->modules[57]->name = ngx_stream_module cycle->modules[57]->type == NGX_CORE_MODULE module->create_conf = (nil)

i=58 cycle->modules[58]->name = ngx_stream_core_module cycle->modules[58]->type != NGX_CORE_MODULE continue

i=59 cycle->modules[59]->name = ngx_stream_log_module cycle->modules[59]->type != NGX_CORE_MODULE continue

i=60 cycle->modules[60]->name = ngx_stream_proxy_module cycle->modules[60]->type != NGX_CORE_MODULE continue

i=61 cycle->modules[61]->name = ngx_stream_upstream_module cycle->modules[61]->type != NGX_CORE_MODULE continue

i=62 cycle->modules[62]->name = ngx_stream_write_filter_module cycle->modules[62]->type != NGX_CORE_MODULE continue

i=63 cycle->modules[63]->name = ngx_stream_ssl_module cycle->modules[63]->type != NGX_CORE_MODULE continue

i=64 cycle->modules[64]->name = ngx_stream_limit_conn_module cycle->modules[64]->type != NGX_CORE_MODULE continue

i=65 cycle->modules[65]->name = ngx_stream_access_module cycle->modules[65]->type != NGX_CORE_MODULE continue

i=66 cycle->modules[66]->name = ngx_stream_geo_module cycle->modules[66]->type != NGX_CORE_MODULE continue

i=67 cycle->modules[67]->name = ngx_stream_map_module cycle->modules[67]->type != NGX_CORE_MODULE continue

i=68 cycle->modules[68]->name = ngx_stream_split_clients_module cycle->modules[68]->type != NGX_CORE_MODULE continue

i=69 cycle->modules[69]->name = ngx_stream_return_module cycle->modules[69]->type != NGX_CORE_MODULE continue

i=70 cycle->modules[70]->name = ngx_stream_set_module cycle->modules[70]->type != NGX_CORE_MODULE continue

i=71 cycle->modules[71]->name = ngx_stream_upstream_hash_module cycle->modules[71]->type != NGX_CORE_MODULE continue

i=72 cycle->modules[72]->name = ngx_stream_upstream_least_conn_module cycle->modules[72]->type != NGX_CORE_MODULE continue

i=73 cycle->modules[73]->name = ngx_stream_upstream_random_module cycle->modules[73]->type != NGX_CORE_MODULE continue

i=74 cycle->modules[74]->name = ngx_stream_upstream_zone_module cycle->modules[74]->type != NGX_CORE_MODULE continue

第一个模块是 ngx_core_module

它的 create_conf 存在


进入 它的 create_conf


第二个 NGX_CORE_MODULE 模块是 ngx_errlog_module

它的 create_conf 是NULL


下一个有 create_conf 的 NGX_CORE_MODULE 模块 是

ngx_openssl_module


下一个有 create_conf 的 NGX_CORE_MODULE 模块 是

ngx_regex_module


接下来是:

senv = environ;
ngx_memzero(&conf, sizeof(ngx_conf_t));
conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));

if (conf.args == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }
    conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
    if (conf.temp_pool == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

    conf.ctx = cycle->conf_ctx;
    conf.cycle = cycle;
    conf.pool = pool;
    conf.log = log;
    conf.module_type = NGX_CORE_MODULE;
    conf.cmd_type = NGX_MAIN_CONF;

    if (ngx_conf_param(&conf) != NGX_CONF_OK) {
        environ = senv;
        ngx_destroy_cycle_pools(&conf);
        return NULL;
    }

    if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
        environ = senv;
        ngx_destroy_cycle_pools(&conf);
        return NULL;
    }

调用 ngx_conf_parse 解析主配置文件( nginx.conf

此次的运行情况: