• NGINX源代码自我总结(一)


    查看源代码入门

        这是一篇关于NGINX的MAIN()函数入门说明文章,相比其他这篇十分枯燥,其实写的时候更是无聊,不过学了这么长时间的WEB开发,连NGINX源代码都没有读下来,总是觉得有些缺憾,希望这一次可以弥补一下。

    一、下载NGINX

    1. 下载地址:http://nginx.org/en/download.html
    2. tar -zxvf *.tar.gz && ./configure && make && sudo make install
    3. 查看NGINX目录有如下文件夹:
      • auto  CHANGES  CHANGES.ru  conf  configure  contrib  html  LICENSE  Makefile  man  objs  README  src

    二、使用gdb跟踪查找入口文件

        很多朋友看见NGINX目录有很多的内容,就会头疼,不知道从哪里开始,下面就分享一个方法。进入objs目录,会发现nginx是可执行文件,使用gdb跟踪一下(如果没有gdb,执行命令:sudo yum install yum安装即可),依次执行如下命令:

    2.1 gdb nginx

    进入nginx程序

    GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
    Copyright (C) 2010 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-redhat-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /root/soft/ngx_openresty-1.4.1.1/build/nginx-1.4.1/objs/nginx...done.

    2.2 l main

    目的是查看main函数

    (gdb) l main
    198    static char **ngx_os_environ;
    199    
    200    
    201    int ngx_cdecl
    202    main(int argc, char *const *argv)
    203    {
    204        ngx_int_t         i;
    205        ngx_log_t        *log;
    206        ngx_cycle_t      *cycle, init_cycle;
    207        ngx_core_conf_t  *ccf;

    2.3 i li main

    查看main()函数的位置

    (gdb) i li main
    Line 203 of "src/core/nginx.c" starts at address 0x4168cb <main> and ends at 0x4168e1 <main+22>.

    如上就知道了入口程序文件是:src/core/nginx.c

    三、main()函数

    int ngx_cdecl
    main(int argc, char *const *argv)
    {
        ngx_int_t         i;
        ngx_log_t        *log;
        ngx_cycle_t      *cycle, init_cycle;
        ngx_core_conf_t  *ccf;
        //上面是四个堆栈的常量,没啥别的意思。nginx的结构都是_t结束的。
        ngx_debug_init();//nginx的函数都是ngx_开头的。下面有解释
    
        if (ngx_strerror_init() != NGX_OK) {
            return 1;//如果启动失败
        }
    
        if (ngx_get_options(argc, argv) != NGX_OK) {
            return 1;//检测命令行参数异常
        }
    
        if (ngx_show_version) {//ngx_show_version是一个全局变量,可以在gdb里面查看(p ngx_show_version或者i var ngx_show_version)
            ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED);
    
            if (ngx_show_help) {//自我帮助信息,执行:"nginx -?"时候输出的信息
                ngx_write_stderr(
                    "Usage: nginx [-?hvVtq] [-s signal] [-c filename] "
                                 "[-p prefix] [-g directives]" NGX_LINEFEED
                                 NGX_LINEFEED
                    "Options:" NGX_LINEFEED
                    "  -?,-h         : this help" NGX_LINEFEED
                    "  -v            : show version and exit" NGX_LINEFEED
                    "  -V            : show version and configure options then exit"
                                       NGX_LINEFEED
                    "  -t            : test configuration and exit" NGX_LINEFEED
                    "  -q            : suppress non-error messages "
                                       "during configuration testing" NGX_LINEFEED
                    "  -s signal     : send signal to a master process: "
                                       "stop, quit, reopen, reload" NGX_LINEFEED
    #ifdef NGX_PREFIX
                    "  -p prefix     : set prefix path (default: "
                                       NGX_PREFIX ")" NGX_LINEFEED
    #else
                    "  -p prefix     : set prefix path (default: NONE)" NGX_LINEFEED
    #endif
                    "  -c filename   : set configuration file (default: "
                                       NGX_CONF_PATH ")" NGX_LINEFEED
                    "  -g directives : set global directives out of configuration "
                                       "file" NGX_LINEFEED NGX_LINEFEED
                    );
            }
    
            if (ngx_show_configure) {
                ngx_write_stderr(
    #ifdef NGX_COMPILER
                    "built by " NGX_COMPILER NGX_LINEFEED
    #endif
    #if (NGX_SSL)
    #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
                    "TLS SNI support enabled" NGX_LINEFEED
    #else
                    "TLS SNI support disabled" NGX_LINEFEED
    #endif
    #endif
                    "configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
            }
    
            if (!ngx_test_config) {
                return 0;
            }
        }
    
        /* TODO */ ngx_max_sockets = -1;
    
        ngx_time_init();//时间初始化
    
    #if (NGX_PCRE)
        ngx_regex_init();//宏开关
    #endif
    
        ngx_pid = ngx_getpid();
    
        log = ngx_log_init(ngx_prefix);//日志初始化
        if (log == NULL) {
            return 1;
        }
    
        /* STUB */
    #if (NGX_OPENSSL)
        ngx_ssl_init(log);//ssh初始化
    #endif
    
        /*
         * init_cycle->log is required for signal handlers and
         * ngx_process_options()
         */
    
        ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));//init_cycle清零
        init_cycle.log = log;
        ngx_cycle = &init_cycle;
    
        init_cycle.pool = ngx_create_pool(1024, log);//建立内存池
        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;
        }
    
        if (ngx_os_init(log) != NGX_OK) {
            return 1;
        }
    
        /*
         * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
         */
    
        if (ngx_crc32_table_init() != NGX_OK) {
            return 1;//crc算法
        }
    
        if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
            return 1;
        }
    
        ngx_max_module = 0;
        for (i = 0; ngx_modules[i]; i++) { //查看一共多少模块
            ngx_modules[i]->index = ngx_max_module++;
        }
    
        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;
        }
    
        if (ngx_test_config) {
            if (!ngx_quiet_mode) {
                ngx_log_stderr(0, "configuration file %s test is successful",
                               cycle->conf_file.data);
            }
    
            return 0;
        }
    
        if (ngx_signal) {
            return ngx_signal_process(cycle, ngx_signal);
        }
    
        ngx_os_status(cycle->log);
    
        ngx_cycle = cycle;
    
        ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
    
        if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
            ngx_process = NGX_PROCESS_MASTER;
        }
    
    #if !(NGX_WIN32)
    
        if (ngx_init_signals(cycle->log) != NGX_OK) {
            return 1;
        }
    
        if (!ngx_inherited && ccf->daemon) {
            if (ngx_daemon(cycle->log) != NGX_OK) {
                return 1;
            }
    
            ngx_daemonized = 1;
        }
    
        if (ngx_inherited) {
            ngx_daemonized = 1;
        }
    
    #endif
    
        if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
            return 1;
        }
    
        if (cycle->log->file->fd != ngx_stderr) {
    
            if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                              ngx_set_stderr_n " failed");
                return 1;
            }
        }
    
        if (log->file->fd != ngx_stderr) {
            if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                              ngx_close_file_n " built-in log failed");
            }
        }
    
        ngx_use_stderr = 0;
    
        if (ngx_process == NGX_PROCESS_SINGLE) {
            ngx_single_process_cycle(cycle);
    
        } else {
            ngx_master_process_cycle(cycle);
        }
    
        return 0;
    }

    无疑,里面的中文内容肯定是我写的注释。

    3.1 ngx_debug_init

    使用gdb执行:"i li ngx_debug_init"

    (gdb) i li ngx_debug_init
    Function "ngx_debug_init" not defined.
    (gdb) 

    没有找到,这个时候只能在文件里面搜索

    @~/soft/ngx_openresty-1.4.1.1/build/nginx-1.4.1/src $ grep -r ngx_debug_init *
    core/nginx.c:    ngx_debug_init();
    os/unix/ngx_freebsd_init.c:ngx_debug_init()
    os/unix/ngx_solaris_config.h:#define ngx_debug_init()
    os/unix/ngx_linux_config.h:#define ngx_debug_init()
    os/unix/ngx_darwin_init.c:ngx_debug_init()
    os/unix/ngx_freebsd.h:void ngx_debug_init(void);
    os/unix/ngx_posix_config.h:#define ngx_debug_init()
    os/unix/ngx_darwin.h:void ngx_debug_init(void);

    可见这是一个操作系统相关的内容,先初始化一下。但是什么都没做,所以gdb搜索不到。

    3.2 ngx_strerror_init

    (gdb) i li ngx_strerror_init
    Line 47 of "src/os/unix/ngx_errno.c" starts at address 0x42d8c9 <ngx_strerror_init> and ends at 0x42d8d7 <ngx_strerror_init+14>.

    然后打开文件ngx_errno.c文件:

    ngx_int_t
    ngx_strerror_init(void)
    {
        char       *msg;
        u_char     *p;
        size_t      len;
        ngx_err_t   err;
        //定义四个堆栈变量
        /*
         * ngx_strerror() is not ready to work at this stage, therefore,
         * malloc() is used and possible errors are logged using strerror().
         */
    
        len = NGX_SYS_NERR * sizeof(ngx_str_t);
        //计算长度,注意NGX_SYS_NERR不是在src里面的,而是编译的时候根据操作系统的不同而生成的不内容,这里是在objs/ngx_auto_config.h里面,定义为:135。
        ngx_sys_errlist = malloc(len);//申请空间
        if (ngx_sys_errlist == NULL) {
            goto failed;
        }
    
        for (err = 0; err < NGX_SYS_NERR; err++) {
            msg = strerror(err);//如果不是以ngx_开头的,都是系统函数或者其他的库函数。这里是建立一个字符串描述这个错误号
            len = ngx_strlen(msg);
    
            p = malloc(len);
            if (p == NULL) {
                goto failed;
            }
    
            ngx_memcpy(p, msg, len);//系统的错误信息拷贝到自己的空间。
            ngx_sys_errlist[err].len = len;
            ngx_sys_errlist[err].data = p;
        }
    
        return NGX_OK;
    
    failed:
    
        err = errno;
        ngx_log_stderr(0, "malloc(%uz) failed (%d: %s)", len, err, strerror(err));
    
        return NGX_ERROR;
    }

    作用是将全局的错误信息复制到一个数组里面,暂时不知道是为什么

    3.3 ngx_init_cycle

    初始化生命周期。core/ngx_cycle.c,这个函数相当的长。

    ngx_cycle_t *
    ngx_init_cycle(ngx_cycle_t *old_cycle)
    {
        void                *rv;
        char               **senv, **env;
        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;
    
        pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
        if (pool == NULL) {
            return NULL;
        }
        pool->log = log;
    
        cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
        if (cycle == NULL) {
            ngx_destroy_pool(pool);
            return NULL;
        }
    
        cycle->pool = pool;
        cycle->log = log;
        cycle->new_log.log_level = NGX_LOG_ERR;
        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->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->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_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;
        }
    
    
        n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10;
    
        cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));
        if (cycle->paths.elts == NULL) {
            ngx_destroy_pool(pool);
            return NULL;
        }
    
        cycle->paths.nelts = 0;
        cycle->paths.size = sizeof(ngx_path_t *);
        cycle->paths.nalloc = n;
        cycle->paths.pool = pool;
    
    
        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;
        }
    
        if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
            != NGX_OK)
        {
            ngx_destroy_pool(pool);
            return NULL;
        }
    
    
        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;
        }
    
        if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))
            != NGX_OK)
        {
            ngx_destroy_pool(pool);
            return NULL;
        }
    
        n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
    
        cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
        if (cycle->listening.elts == NULL) {
            ngx_destroy_pool(pool);
            return NULL;
        }
    
        cycle->listening.nelts = 0;
        cycle->listening.size = sizeof(ngx_listening_t);
        cycle->listening.nalloc = n;
        cycle->listening.pool = pool;
    
    
        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;
        }
    
    
        if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) {
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed");
            ngx_destroy_pool(pool);
            return NULL;
        }
    
        /* on Linux gethostname() silently truncates name that does not fit */
    
        hostname[NGX_MAXHOSTNAMELEN - 1] = '';
        cycle->hostname.len = ngx_strlen(hostname);
    
        cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len);
        if (cycle->hostname.data == NULL) {
            ngx_destroy_pool(pool);
            return NULL;
        }
    
        ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);
    
    
        for (i = 0; ngx_modules[i]; i++) {
            if (ngx_modules[i]->type != NGX_CORE_MODULE) {
                continue;
            }
    
            module = ngx_modules[i]->ctx;
    
            if (module->create_conf) {
                rv = module->create_conf(cycle);
                if (rv == NULL) {
                    ngx_destroy_pool(pool);
                    return NULL;
                }
                cycle->conf_ctx[ngx_modules[i]->index] = rv;
            }
        }
    
    
        senv = environ;
    
    
        ngx_memzero(&conf, sizeof(ngx_conf_t));
        /* STUB: init array ? */
        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 0
        log->log_level = NGX_LOG_DEBUG_ALL;
    #endif
    
        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;
        }
        //cycle->conf,指向一块内存,多级指针数组,共44个模块。第0个是核心模块的数据结构,ngx_core_module,如后面3.5所示;第3个是一个指向指针的指针,ngx_events_module。
    //第六个指向的ngx的http模块,ngx_http_core数据结构,如3.6所示
    if (ngx_test_config && !ngx_quiet_mode) { ngx_log_stderr(0, "the configuration file %s syntax is ok", cycle->conf_file.data); } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) == NGX_CONF_ERROR) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } } if (ngx_process == NGX_PROCESS_SIGNALLER) { return cycle; } ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ngx_test_config) { if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } } else if (!ngx_is_init_cycle(old_cycle)) { /* * we do not create the pid file in the first ngx_init_cycle() call * because we need to write the demonized process pid */ old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (ccf->pid.len != old_ccf->pid.len || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0) { /* new pid file name */ if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } ngx_delete_pidfile(old_cycle); } } if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) { goto failed; } if (ngx_create_paths(cycle, ccf->user) != NGX_OK) { goto failed; } if (cycle->new_log.file == NULL) { cycle->new_log.file = ngx_conf_open_file(cycle, &error_log); if (cycle->new_log.file == NULL) { goto failed; } } /* open the new files */ part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } file[i].fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, "log: %p %d "%s"", &file[i], file[i].fd, file[i].name.data); if (file[i].fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_open_file_n " "%s" failed", file[i].name.data); goto failed; } #if !(NGX_WIN32) if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fcntl(FD_CLOEXEC) "%s" failed", file[i].name.data); goto failed; } #endif } cycle->log = &cycle->new_log; pool->log = &cycle->new_log; /* create shared memory */ part = &cycle->shared_memory.part; shm_zone = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; i = 0; } if (shm_zone[i].shm.size == 0) { ngx_log_error(NGX_LOG_EMERG, log, 0, "zero size shared memory zone "%V"", &shm_zone[i].shm.name); goto failed; } shm_zone[i].shm.log = cycle->log; opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (n = 0; /* void */ ; n++) { if (n >= opart->nelts) { if (opart->next == NULL) { break; } opart = opart->next; oshm_zone = opart->elts; n = 0; } if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) { continue; } if (ngx_strncmp(shm_zone[i].shm.name.data, oshm_zone[n].shm.name.data, shm_zone[i].shm.name.len) != 0) { continue; } if (shm_zone[i].tag == oshm_zone[n].tag && shm_zone[i].shm.size == oshm_zone[n].shm.size) { shm_zone[i].shm.addr = oshm_zone[n].shm.addr; if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data) != NGX_OK) { goto failed; } goto shm_zone_found; } ngx_shm_free(&oshm_zone[n].shm); break; } if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) { goto failed; } if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) { goto failed; } if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) { goto failed; } shm_zone_found: continue; } /* handle the listening sockets */ if (old_cycle->listening.nelts) { ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { ls[i].remain = 0; } nls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].ignore) { continue; } if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; ls[i].remain = 1; if (ls[n].backlog != nls[i].backlog) { nls[n].listen = 1; } #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) /* * FreeBSD, except the most recent versions, * could not remove accept filter */ nls[n].deferred_accept = ls[i].deferred_accept; if (ls[i].accept_filter && nls[n].accept_filter) { if (ngx_strcmp(ls[i].accept_filter, nls[n].accept_filter) != 0) { nls[n].delete_deferred = 1; nls[n].add_deferred = 1; } } else if (ls[i].accept_filter) { nls[n].delete_deferred = 1; } else if (nls[n].accept_filter) { nls[n].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[n].deferred_accept && !nls[n].deferred_accept) { nls[n].delete_deferred = 1; } else if (ls[i].deferred_accept != nls[n].deferred_accept) { nls[n].add_deferred = 1; } #endif break; } } if (nls[n].fd == -1) { nls[n].open = 1; } } } else { ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { ls[i].open = 1; #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) if (ls[i].accept_filter) { ls[i].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[i].deferred_accept) { ls[i].add_deferred = 1; } #endif } } if (ngx_open_listening_sockets(cycle) != NGX_OK) { goto failed; } if (!ngx_test_config) { ngx_configure_listening_sockets(cycle); } /* commit the new cycle configuration */ if (!ngx_use_stderr && cycle->log->file->fd != ngx_stderr) { if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_set_stderr_n " failed"); } } pool->log = cycle->log; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_module) { if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */ exit(1); } } } /* close and delete stuff that lefts from an old cycle */ /* free the unnecessary shared memory */ opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (i = 0; /* void */ ; i++) { if (i >= opart->nelts) { if (opart->next == NULL) { goto old_shm_zone_done; } opart = opart->next; oshm_zone = opart->elts; i = 0; } part = &cycle->shared_memory.part; shm_zone = part->elts; for (n = 0; /* void */ ; n++) { if (n >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; n = 0; } if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len && ngx_strncmp(oshm_zone[i].shm.name.data, shm_zone[n].shm.name.data, oshm_zone[i].shm.name.len) == 0) { goto live_shm_zone; } } ngx_shm_free(&oshm_zone[i].shm); live_shm_zone: continue; } old_shm_zone_done: /* close the unnecessary listening sockets */ ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].remain || ls[i].fd == -1) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " listening socket on %V failed", &ls[i].addr_text); } #if (NGX_HAVE_UNIX_DOMAIN) if (ls[i].sockaddr->sa_family == AF_UNIX) { u_char *name; name = ls[i].addr_text.data + sizeof("unix:") - 1; ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "deleting socket %s", name); if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_delete_file_n " %s failed", name); } } #endif } /* close the unnecessary open files */ part = &old_cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " "%s" failed", file[i].name.data); } } ngx_destroy_pool(conf.temp_pool); if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) { /* * perl_destruct() frees environ, if it is not the same as it was at * perl_construct() time, therefore we save the previous cycle * environment before ngx_conf_parse() where it will be changed. */ env = environ; environ = senv; ngx_destroy_pool(old_cycle->pool); cycle->old_cycle = NULL; environ = env; return cycle; } if (ngx_temp_pool == NULL) { ngx_temp_pool = ngx_create_pool(128, cycle->log); if (ngx_temp_pool == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "could not create ngx_temp_pool"); exit(1); } n = 10; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { exit(1); } ngx_old_cycles.nelts = 0; ngx_old_cycles.size = sizeof(ngx_cycle_t *); ngx_old_cycles.nalloc = n; ngx_old_cycles.pool = ngx_temp_pool; ngx_cleaner_event.handler = ngx_clean_old_cycles; ngx_cleaner_event.log = cycle->log; ngx_cleaner_event.data = &dumb; dumb.fd = (ngx_socket_t) -1; } ngx_temp_pool->log = cycle->log; old = ngx_array_push(&ngx_old_cycles); if (old == NULL) { exit(1); } *old = old_cycle; if (!ngx_cleaner_event.timer_set) { ngx_add_timer(&ngx_cleaner_event, 30000); ngx_cleaner_event.timer_set = 1; } return cycle; failed: if (!ngx_is_init_cycle(old_cycle)) { old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx,ngx_core_module); if (old_ccf->environment) { environ = old_ccf->environment; } } /* rollback the new cycle configuration */ part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " "%s" failed", file[i].name.data); } } if (ngx_test_config) { ngx_destroy_cycle_pools(&conf); return NULL; } ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { if (ls[i].fd == -1 || !ls[i].open) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); } } ngx_destroy_cycle_pools(&conf); return NULL; }

    修改配置参数之后,可以不重新启动服务,而可以生效。他把所有nginx的参数都放入到一个参数里面,如果修改,那么他会慢慢的修改过来。

    3.4 ngx_cycle_s

    文件:src/core/ngx_cycle.h 

    struct ngx_cycle_s {
        void                  ****conf_ctx;//解析配置文件,
        ngx_pool_t               *pool;
    
        ngx_log_t                *log;
        ngx_log_t                 new_log;
    
        ngx_connection_t        **files;
        ngx_connection_t         *free_connections;
        ngx_uint_t                free_connection_n;
    
        ngx_queue_t               reusable_connections_queue;
    
        ngx_array_t               listening;
        ngx_array_t               paths;
        ngx_list_t                open_files;
        ngx_list_t                shared_memory;
    
        ngx_uint_t                connection_n;
        ngx_uint_t                files_n;
    
        ngx_connection_t         *connections;
        ngx_event_t              *read_events;
        ngx_event_t              *write_events;
    
        ngx_cycle_t              *old_cycle;
    
        ngx_str_t                 conf_file;
        ngx_str_t                 conf_param;
        ngx_str_t                 conf_prefix;
        ngx_str_t                 prefix;
        ngx_str_t                 lock_file;
        ngx_str_t                 hostname;
    };

     3.5 ngx_core_conf_t 结构体

    typedef struct {
         ngx_flag_t               daemon;
         ngx_flag_t               master;
    
         ngx_msec_t               timer_resolution;
    
         ngx_int_t                worker_processes; //进程数量
         ngx_int_t                debug_points;
    
         ngx_int_t                rlimit_nofile;
         ngx_int_t                rlimit_sigpending;
         off_t                    rlimit_core;
    
         int                      priority;
    
         ngx_uint_t               cpu_affinity_n;
         uint64_t                *cpu_affinity;
    
         char                    *username;
         ngx_uid_t                user;
         ngx_gid_t                group;
    
         ngx_str_t                working_directory;
         ngx_str_t                lock_file;
    
         ngx_str_t                pid;
         ngx_str_t                oldpid;
    
         ngx_array_t              env;
         char                   **environment;
    
    #if (NGX_THREADS)
         ngx_int_t                worker_threads;
         size_t                   thread_stack_size;
    #endif
    
    } ngx_core_conf_t;

    3.6 ngx_http_conf_cxt_t结构体

    在src/http/ngx_http_config.h里面

       17 typedef struct {
       18     void        **main_conf;  //http的子模块
       19     void        **srv_conf;   //所有server的参数
       20     void        **loc_conf;   //所有url的参数
       21 } ngx_http_conf_ctx_t;
  • 相关阅读:
    Java多线程性能优化
    It is indirectly referenced from required .class files
    Switch基本知识
    HibernateTemplate 查询
    Hibernate工作原理及为什么要用?
    深入Java集合学习系列:HashMap的实现原理
    sql查询语句中的乱码 -- 前面加N
    Windows 8.1内置微软五笔输入法
    the rendering library is more recent than your version of android studio
    JBoss vs. Tomcat
  • 原文地址:https://www.cnblogs.com/liqiu/p/3500357.html
Copyright © 2020-2023  润新知