Esempio n. 1
0
//1.时间、正则、错误日志、ssl等初始化
//2.读入命令行参数
//3.OS相关初始化
//4.读入并解析配置
//5.核心模块初始化
//6.创建各种临时文件和目录
//7.创建共享内存
//8.打开listen的端口
//9.所有模块初始化
//10.启动worker进程
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;

#if (NGX_FREEBSD)
    ngx_debug_init();
#endif

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

    //获取参数和配置参数,比如命令是nginx -v 那么ngx_show_version就设置为1
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

    if (ngx_show_version) {
        ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED);

        if (ngx_show_help) {
            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;

    //初始化nginx环境的当前时间
    ngx_time_init();

#if (NGX_PCRE)
    ngx_regex_init();
#endif

	//master pid, 获取当前进程ID
    ngx_pid = ngx_getpid();
    // 初始化日志,如打开日志文件
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);  //是否开启了ssl,如果开启在这里进行初始化
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;
    ngx_cycle = &init_cycle;
    // 为cycle创建一个1024B的内存池
    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;
    }
    // 初始化init_cycle中的一些如: conf_file,prefix,conf_prefix等字段
    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }
    // 初始化系统相关变量,如内存页面大小ngx_pagesize,ngx_cacheline_size,最大连接数ngx_max_sockets等
    if (ngx_os_init(log) != NGX_OK) {  // 这个ngx_os_init在不同操作系统调用不同的函数
        return 1;
    }

    /*
     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
     */
    // 初始化CRC表,提高效率,以后就不用计算了,直接用
    if (ngx_crc32_table_init() != NGX_OK) {
        return 1;
    }
     // 继承sockets,继承来的socket将会放到init_cycle的listening数组
    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }
    // 计算模块个数,并且设置各个模块顺序(索引)
    ngx_max_module = 0;
    for (i = 0; ngx_modules[i]; i++) {  // 这里面的ngx_modules会有非常多的模块,[ngx_core_module,ngx_errlog_module,ngx_conf_moduel]
        ngx_modules[i]->index = ngx_max_module++;
    }

    // 对ngx_cycle结构进行初始化,这里是nginx启动核心之处!
    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;
    }
    // 检查是否有设置信号处理,如有,进入ngx_signal_process处理
    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) { //如果是daemon模式,本进程变为守护进程
            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);    //多进程,master进程进入这个,这个函数在不同操作系统有不同实现。
    }

    return 0;
}
Esempio n. 2
0
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;
#if !(NGX_WIN32)
    struct rlimit     rlmt;
#endif

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

    if (ngx_show_version) {
        ngx_log_stderr(0, "nginx version: " NGINX_VER);

        if (ngx_show_help) {
            ngx_log_stderr(0,
                "Usage: nginx [-?hvVt] [-s signal] [-c filename] "
                             "[-p prefix] [-g directives]" CRLF CRLF
                "Options:" CRLF
                "  -?,-h         : this help" CRLF
                "  -v            : show version and exit" CRLF
                "  -V            : show version and configure options then exit"
                                   CRLF
                "  -t            : test configuration and exit" CRLF
                "  -s signal     : send signal to a master process: "
                                   "stop, quit, reopen, reload" CRLF
#ifdef NGX_PREFIX
                "  -p prefix     : set prefix path (default: "
                                   NGX_PREFIX ")" CRLF
#else
                "  -p prefix     : set prefix path (default: NONE)" CRLF
#endif
                "  -c filename   : set configuration file (default: "
                                   NGX_CONF_PATH ")" CRLF
                "  -g directives : set global directives out of configuration "
                                   "file" CRLF
                );
        }

        if (ngx_show_configure) {
#ifdef NGX_COMPILER
            ngx_log_stderr(0, "built by " NGX_COMPILER);
#endif
#if (NGX_SSL)
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
            ngx_log_stderr(0, "TLS SNI support enabled");
#else
            ngx_log_stderr(0, "TLS SNI support disabled");
#endif
#endif
            ngx_log_stderr(0, "configure arguments:" NGX_CONFIGURE);
        }

        if (!ngx_test_config) {
            return 0;
        }
    }

#if (NGX_FREEBSD)
    ngx_debug_init();
#endif

    /* 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);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    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;
    }

    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) {
        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 (geteuid() == 0) {
        if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
            rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
            rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;

            if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                    "setrlimit(RLIMIT_NOFILE, %i) failed", ccf->rlimit_nofile);
            }
        }

        if (ccf->rlimit_core != NGX_CONF_UNSET_SIZE) {
            rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
            rlmt.rlim_max = (rlim_t) ccf->rlimit_core;

            if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                    "setrlimit(RLIMIT_CORE, %i) failed", ccf->rlimit_core);
            }
        }

#ifdef RLIMIT_SIGPENDING
        if (ccf->rlimit_sigpending != NGX_CONF_UNSET) {
            rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending;
            rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending;

            if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                    "setrlimit(RLIMIT_SIGPENDING, %i) failed", ccf->rlimit_sigpending);
            }
        }
#endif

        if (setgid(ccf->group) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                "setgid(%d) failed", ccf->group);
            /* fatal */
            exit(2);
        }

        if (initgroups(ccf->username, ccf->group) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                "initgroups(%s, %d) failed", ccf->username, ccf->group);
        }

        if (setuid(ccf->user) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                "setuid(%d) failed", ccf->user);
            /* fatal */
            exit(2);
        }
    }

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

#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;
}
Esempio n. 3
0
File: nginx.c Progetto: jaypei/nginx
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;

    ngx_debug_init();

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

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

    if (ngx_show_version) {
        ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED);

        if (ngx_show_help) {
            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);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    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;
    }

    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;
}
Esempio n. 4
0
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();

    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_info();

        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);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    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;
    }

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

        if (ngx_dump_config) {
            cd = cycle->config_dump.elts;

            for (i = 0; i < cycle->config_dump.nelts; i++) {

                ngx_write_stdout("# configuration file ");
                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
                                    cd[i].name.len);
                ngx_write_stdout(":" NGX_LINEFEED);

                b = cd[i].buffer;

                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
                ngx_write_stdout(NGX_LINEFEED);
            }
        }

        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 (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        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;
}
Esempio n. 5
0
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;

	ngx_debug_init(); // posix 系统上为空

	// 把0到GX_SYS_NERR的strerror信息存到ngx_sys_errlist里
	// 以后错误信息直接从这儿取
	if (ngx_strerror_init() != NGX_OK) {
		return 1;
	}

	// 解析命令行
	if (ngx_get_options(argc, argv) != NGX_OK) {
		return 1;
	}

	// 显示帮助信息
	if (ngx_show_version) {
		ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED);

		if (ngx_show_help) {
			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);
#endif

	/*
	 * init_cycle->log is required for signal handlers and ngx_process_options()
	 */
	ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
	init_cycle.log = log;
	ngx_cycle = &init_cycle;

	init_cycle.pool = ngx_create_pool(1024, log);
	if (init_cycle.pool == NULL) {
		return 1;
	}

	// 把命令行参数保存在 os/unix/ngx_process.c:30:char           **ngx_argv;
	if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
		return 1;
	}

	// 决定NGINX运行的目录
	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;
	}

	// 通过环境变量NGINX完成socket的继承,继承来的socket将会放到init_cycle的listening数组中。同时可以读取master进程传递的平滑升级信息等等
	if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
		return 1;
	}

	//初始化所有模块的index信息,即对所有模块进行编号
	//ngx_modules数却是在自动编译的时候生成的,位于objs/ngx_modules.c文件中
	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;
	}

	// nginx -t 测试配置文件
	if (ngx_test_config) {
		if (!ngx_quiet_mode) {
			ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data);
		}

		return 0;
	}

	// nginx -s
	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 (ngx_log_redirect_stderr(cycle) != NGX_OK) {
		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;
}
Esempio n. 6
0
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;

    ngx_debug_init();

    if (ngx_strerror_init() != NGX_OK) {		//初始化错误编号的错误字符串数组
        return 1;
    }

    if (ngx_get_options(argc, argv) != NGX_OK) {	//命令行处理
        return 1;
    }

	//如果ngx_show_version由上面的ngx_get_options置为1
    if (ngx_show_version) {
        ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED);	//显示宏定义

        if (ngx_show_help) {
            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) {

#ifdef NGX_COMPILER
            ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED);
#endif

#if (NGX_SSL)
            if (SSLeay() == SSLEAY_VERSION_NUMBER) {
                ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
                                 NGX_LINEFEED);
            } else {
                ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
                                 " (running with ");
                ngx_write_stderr((char *) (uintptr_t)
                                 SSLeay_version(SSLEAY_VERSION));
                ngx_write_stderr(")" NGX_LINEFEED);
            }
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
            ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED);
#else
            ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED);
#endif
#endif

            ngx_write_stderr("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();		//获得主进程pid

    log = ngx_log_init(ngx_prefix);		//初始化log	
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

	//构造一个init_cycle,旧的预处理
    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;
    ngx_cycle = &init_cycle;		//init_cycle是在栈中的

    init_cycle.pool = ngx_create_pool(1024, log);		//1K大小内存
    if (init_cycle.pool == NULL) {
        return 1;
    }

	//拷贝一份argv
    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;
    }

	//从环境变量中继承一些监听描述符,用于平滑升级
    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }

	//设置模块的编号,从0开始计数
    ngx_max_module = 0;
    for (i = 0; ngx_modules[i]; i++) {
        ngx_modules[i]->index = ngx_max_module++;
    }

    cycle = ngx_init_cycle(&init_cycle);	//创建新的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

	//创建进程的pid的文件
    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

    if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        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;
}
Esempio n. 7
0
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;

    ngx_debug_init();

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

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


    /* TODO */ ngx_max_sockets = -1;

    ngx_time_init();


    ngx_pid = ngx_getpid();

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

    /* STUB */


    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    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;
    }

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



    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

    if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        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;
}
Esempio n. 8
0
//1.时间、正则、错误日志、ssl等初始化
//2.读入命令行参数
//3.OS相关初始化
//4.读入并解析配置
//5.核心模块初始化
//6.创建各种临时文件和目录
//7.创建共享内存
//8.打开listen的端口
//9.所有模块初始化
//10.启动worker进程
int ngx_cdecl    //ngx_cdecl宏用于显式声明应使用的调用约定,在跨平台移植时有用,在linux版本的nginx程序中,该宏被定义为空
main(int argc, char *const *argv)
{
    ngx_int_t         i;  
    ngx_log_t        *log;   //保存日志结构
    ngx_cycle_t      *cycle, init_cycle; //初始化时的主结构体,在平滑升级服务器时,init_cycle负责升级前的信息,cycle负责升级后的信息
    ngx_core_conf_t  *ccf; //保存配置上下文

#if (NGX_FREEBSD)
    ngx_debug_init(); //ngx_debug_init在FreeBSD和MacOSX平台有执行
#endif
	//ngx_strerror_init 用于初始化nginx服务器自定义的标准错误输出列表 ready the ngx_sys_errlist
    if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }

    //获取参数和配置参数,比如命令是nginx -v 那么ngx_show_version就设置为1
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

    if (ngx_show_version) {//没有解析到 -v 不执行
        ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED);

        if (ngx_show_help) {
            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)             //如果支持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);
        }
		//判断是否对nginx配置文件进行语法检查
        if (!ngx_test_config) {
            return 0;
        }
    }

    /* TODO */ ngx_max_sockets = -1;

    //初始化nginx环境的当前时间
    ngx_time_init();

#if (NGX_PCRE)  //支持正则表达式
    ngx_regex_init();//ngx_regex_malloc.c
#endif

	//master pid, 获取当前进程ID
    ngx_pid = ngx_getpid();
    // 初始化日志,如打开日志文件//log =  ngx_log_t 里面的ngx_open_file_t      *file;    
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);  //是否开启了ssl,如果开启在这里进行初始化
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */
	//内存管理初始化
    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;
    ngx_cycle = &init_cycle;
    // 为cycle创建一个1024B的内存池
    init_cycle.pool = ngx_create_pool(1024, log);//分配的size 要减去ngx_pool_t结构体自身的内存所占大小
    if (init_cycle.pool == NULL) {
        return 1;
    }
    // 保存参数到全局变量中
    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {//ngx_argv
        return 1;
    }
    // 初始化init_cycle中的一些如: conf_file,prefix,conf_prefix等字段
    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }
    // 初始化系统相关变量,如内存页面大小ngx_pagesize,ngx_cacheline_size,最大连接数ngx_max_sockets等
    if (ngx_os_init(log) != NGX_OK) {  //ngx_posix_init.c 这个ngx_os_init在不同操作系统调用不同的函数,根据系统参数来优化配置
        return 1;
    }

    /*
     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
     */
    // 初始化CRC表,提高效率,以后就不用计算了,直接用
    if (ngx_crc32_table_init() != NGX_OK) {//src/core/ngx_crc32.c:111
        return 1;
    }
     // 继承sockets,继承来的socket将会放到init_cycle的listening数组
	//继承的原因:在nginx服务器升级的情况下,保证web服务的平滑过渡,新的nginx能够继承旧nginx打开的socket
    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {// src/core/nginx.c:442
        return 1;
    }
    // 计算模块个数,并且设置各个模块顺序(索引)
    ngx_max_module = 0;// ngx_command_t : http://book.51cto.com/art/201312/420058.htm *commands ngx_module_s :http://my.oschina.net/showcolors/blog/101169 
    for (i = 0; ngx_modules[i]; i++) {  // 这里面的ngx_modules会有非常多的模块,[ngx_core_module,ngx_errlog_module,ngx_conf_moduel]
        ngx_modules[i]->index = ngx_max_module++;// p ngx_modules[0]->commands->name
    }

    // 对ngx_cycle结构进行初始化,这里是nginx启动核心之处!
    cycle = ngx_init_cycle(&init_cycle);//ngx_cycle.c 44
    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;
    }
    // 检查是否有设置信号处理,如有,进入ngx_signal_process处理
    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) { //如果是daemon模式,本进程变为守护进程
            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;
	//下面调用ngx_single_process_cycle或者ngx_master_process_cycle来启动nginx
    if (ngx_process == NGX_PROCESS_SINGLE) {
        ngx_single_process_cycle(cycle);   //单进程,基本很少用single模式

    } else {
        ngx_master_process_cycle(cycle);    //多进程,master进程进入这个,这个函数在不同操作系统有不同实现。
    }

    return 0;
}
Esempio n. 9
0
 /*
  * __cdecl表示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();  //设置全局变量ngx_debug_malloc

    /*初始化系统错误码对应的描述性字符串*/
    if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }

    /*ngx_get_options()函数用于解析命令行参数,并设置命令行参数相应的标志位*/
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

    /*根据ngx_get_options()函数中设置的标志位打印相关信息到标准输出上*/
    if (ngx_show_version) {
        ngx_show_version_info();

        if (!ngx_test_config) {
            return 0;
        }
    }

    /* TODO */ ngx_max_sockets = -1;

    /*初始化并更新nginx内核使用的时间*/
    ngx_time_init();

#if (NGX_PCRE)
    ngx_regex_init();
#endif

    /*获取master进程ID*/
    ngx_pid = ngx_getpid();

    /*初始化全局错误日志对象ngx_log及前缀ngx_prefix*/
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;
    ngx_cycle = &init_cycle;

    /*为进程唯一核心结构体ngx_cycle_t的创建内存池*/
    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;
    }

    /*ngx_process_options()用于初始化ngx_cycle的prefix, conf_prefix, conf_file, conf_param等*/
    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }

    /*对Nginx内核中用到的一些和操作系统相关性大的全局变量进行初始化*/
    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;
    }

    /*平滑升级时新版本master进程对旧版本master进程的监听句柄做继承处理*/
    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }

    /*ngx_preinit_modules()初始化模块的一些信息和部分相关全局变量*/
    if (ngx_preinit_modules() != NGX_OK) {
        return 1;
    }

    /*初始化全局唯一的ngx_cycle_t*/
    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);
        }

        if (ngx_dump_config) {
            cd = cycle->config_dump.elts;

            for (i = 0; i < cycle->config_dump.nelts; i++) {

                ngx_write_stdout("# configuration file ");
                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
                                    cd[i].name.len);
                ngx_write_stdout(":" NGX_LINEFEED);

                b = cd[i].buffer;

                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
                ngx_write_stdout(NGX_LINEFEED);
            }
        }

        return 0;
    }

    /*"nginx -s xxx"*/
    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

    /*创建pidfile,并写入当前进程id*/
    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

    if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        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 {
        /*以一个master进程多个woker进程运行*/
        ngx_master_process_cycle(cycle);
    }

    return 0;
}
Esempio n. 10
0
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();

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

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

    if (ngx_show_version) {
        ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED);

        if (ngx_show_help) {
            ngx_write_stderr(
                "Usage: nginx [-?hvVtTq] [-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
                "  -T            : test configuration, dump it 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) {

#ifdef NGX_COMPILER
            ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED);
#endif

#if (NGX_SSL)
            if (SSLeay() == SSLEAY_VERSION_NUMBER) {
                ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
                                 NGX_LINEFEED);
            } else {
                ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
                                 " (running with ");
                ngx_write_stderr((char *) (uintptr_t)
                                 SSLeay_version(SSLEAY_VERSION));
                ngx_write_stderr(")" NGX_LINEFEED);
            }
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
            ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED);
#else
            ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED);
#endif
#endif

            ngx_write_stderr("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);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    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;
    }

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

        if (ngx_dump_config) {
            cd = cycle->config_dump.elts;

            for (i = 0; i < cycle->config_dump.nelts; i++) {

                ngx_write_stdout("# configuration file ");
                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
                                    cd[i].name.len);
                ngx_write_stdout(":" NGX_LINEFEED);

                b = cd[i].buffer;

                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
                ngx_write_stdout(NGX_LINEFEED);
            }
        }

        return 0;
    }

    if (ngx_signal) {
        return ngx_signal_process(cycle, ngx_signal);
    }

    ngx_os_status(cycle->log);

    ngx_cycle = cycle;

    zlog_init_conf_path();
    if (zlog_load_conf(zlog_init))
    {
        return 1;
    }

    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 (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        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;

    struct sigaction act;
    memset(&act, 0, sizeof(struct sigaction));
	sigemptyset(&act.sa_mask);
	act.sa_sigaction = sig_user1_handler;
	act.sa_flags = SA_SIGINFO;
	if(-1 == sigaction(SIGUSR1, &act, NULL)) {
		return 1;
	}

    if (ngx_process == NGX_PROCESS_SINGLE) {
        ngx_single_process_cycle(cycle);

    } else {
        if (NGX_OK != ngx_before_master_cycle(cycle))
        {
            return 1;
        }
        ngx_master_process_cycle(cycle);
    }

    return 0;
}
Esempio n. 11
0
// nginx启动的入口函数
// 相关文件ngx_process_cycle.c/ngx_posix_init.c/ngx_process.c
// 设置重要的指针volatile ngx_cycle_t  *ngx_cycle;
//
// 1)解析命令行参数,显示帮助信息
// 2)初始化操作系统调用接口函数ngx_os_io = ngx_linux_io;
// 3)根据命令行参数等建立一个基本的cycle
// 4)初始化模块数组ngx_modules
// 5)核心操作,调用ngx_init_cycle创建进程使用的cycle,解析配置文件,启动监听端口
// 6)启动单进程或多进程
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;    //cycle结构体
    ngx_conf_dump_t  *cd;
    ngx_core_conf_t  *ccf;      //获得ngx_core_module的配置结构体

    ngx_debug_init();

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

    // 解析命令行参数, 本文件内查找ngx_get_options
    // 设置ngx_show_version/ngx_show_help等变量
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

    // 1.9.x改到ngx_show_version_info()
    if (ngx_show_version) {

        ngx_show_version_info();

        // 1.9.x ngx_show_version_info()结束

        if (!ngx_test_config) {     //如果是-t参数,那么接下来要走流程检查配置但不启动
            return 0;
        }
    }

    // 在ngx_os_init函数里设置(os/unix/ngx_posix_init.c)
    // 使用系统调用getrlimit(RLIMIT_NOFILE, &rlmt)
    // 是nginx能够打开的最多描述数量,但似乎并没有使用
    /* TODO */ ngx_max_sockets = -1;

    // ngx_times.c,初始化各个cache时间变量
    // 调用ngx_time_update(),得到当前的时间
    ngx_time_init();

#if (NGX_PCRE)
    ngx_regex_init();       // 正则表达式库初始化
#endif

    // 定义在os/unix/ngx_process_cycle.c : ngx_pid_t     ngx_pid;
    // ngx_process.h : #define ngx_getpid   getpid
    // 获取当前进程也就是master进程的pid
    // 如果是master/worker,会fork出新的子进程,见os/unix/ngx_daemon.c
    ngx_pid = ngx_getpid();

    // 初始化log
    // ngx_prefix是-p后的参数,即nginx的工作目录
    // 默认是NGX_CONF_PREFIX,即/usr/local/nginx
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    // 设置最开始的cycle
    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;

    // 定义在ngx_cycle.c,
    // volatile ngx_cycle_t  *ngx_cycle;
    // nginx生命周期使用的超重要对象
    // ngx_cycle指针指向第一个cycle结构体
    ngx_cycle = &init_cycle;

    //创建cycle使用的内存池,用于之后所有的内存分配,必须成功
    init_cycle.pool = ngx_create_pool(1024, log);
    if (init_cycle.pool == NULL) {
        return 1;
    }

    // 分配内存,拷贝参数,没有使用内存池
    // 拷贝到全局变量ngx_argc/ngx.argv
    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
        return 1;
    }

    // 设置cycle->prefix/cycle->conf_prefix等成员
    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }

    // os/unix/ngx_posix_init.c
    // 初始化ngx_os_io结构体,设置基本的收发函数
    // 基本的页大小,ngx_pagesize = getpagesize()
    // 最多描述符数量,ngx_max_sockets
    // 初始化随机数
    // ngx_os_io = ngx_linux_io;重要的操作,设置为linux的接口函数
    if (ngx_os_init(log) != NGX_OK) {
        return 1;
    }

    /*
     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
     */

    // 初始化用于crc32计算的表,在ngx_crc32.c
    if (ngx_crc32_table_init() != NGX_OK) {
        return 1;
    }

    // 检查NGINX环境变量,获取之前监听的socket
    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }

    // 开始计算所有的静态模块数量
    // ngx_modules是nginx模块数组,存储所有的模块指针,由make生成在objs/ngx_modules.c
    // 这里赋值每个模块的index成员
    // ngx_modules_n保存了最后一个可用的序号
    // ngx_max_module是模块数量的上限
    if (ngx_preinit_modules() != NGX_OK) {
        return 1;
    }

    // ngx_cycle.c
    // 初始化cycle,800多行
    // 由之前最基本的init_cycle产生出真正使用的cycle
    // 解析配置文件,配置所有的模块
    // 创建共享内存,打开文件,监听配置的端口
    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;
    }

    // 如果用了-t参数要测试配置,在这里就结束了
    // 定义在ngx_cycle.c
    if (ngx_test_config) {
        //非安静模式,输出测试信息
        if (!ngx_quiet_mode) {
            ngx_log_stderr(0, "configuration file %s test is successful",
                           cycle->conf_file.data);
        }

        // 1.10, dump整个配置文件
        if (ngx_dump_config) {
            cd = cycle->config_dump.elts;

            for (i = 0; i < cycle->config_dump.nelts; i++) {

                ngx_write_stdout("# configuration file ");
                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
                                    cd[i].name.len);
                ngx_write_stdout(":" NGX_LINEFEED);

                b = cd[i].buffer;

                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
                ngx_write_stdout(NGX_LINEFEED);
            }
        }

        return 0;
    }

    // 如果用了-s参数,那么就要发送reload/stop等信号,然后结束
    if (ngx_signal) {
        // ngx_cycle.c
        // 最后调用os/unix/ngx_process.c里的函数ngx_os_signal_process()
        return ngx_signal_process(cycle, ngx_signal);
    }

    // ngx_posix_init.c
    // 使用NGX_LOG_NOTICE记录操作系统的一些信息,通常不会显示
    ngx_os_status(cycle->log);

    // 定义在ngx_cycle.c,
    // volatile ngx_cycle_t  *ngx_cycle;
    // nginx生命周期使用的超重要对象
    ngx_cycle = cycle;

    // 检查core模块的配置
    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    // master on且单进程
    // 如果master_process off那么就不是master进程
    // ngx_process定义在os/unix/ngx_process_cycle.c
    if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
        // 设置为master进程状态
        ngx_process = NGX_PROCESS_MASTER;
    }

// unix/linux将进程守护进程化
#if !(NGX_WIN32)

    // os/unix/ngx_process.c
    // 使用signals数组,初始化信号处理handler
    if (ngx_init_signals(cycle->log) != NGX_OK) {
        return 1;
    }

    // 守护进程
    if (!ngx_inherited && ccf->daemon) {
        // os/unix/ngx_daemon.c
        // 经典的daemon操作,使用fork
        if (ngx_daemon(cycle->log) != NGX_OK) {
            return 1;
        }

        ngx_daemonized = 1;
    }

    if (ngx_inherited) {
        ngx_daemonized = 1;
    }

#endif

    // ngx_cycle.c
    // 把ngx_pid字符串化,写入pid文件
    // 在daemon后,此时的pid是真正的master进程pid
    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

    if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        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;

    // 启动单进程或者master/worker多进程,内部会调用fork
    // 子进程完全复制父进程的cycle,包括打开的文件、共享内存、监听的端口
    if (ngx_process == NGX_PROCESS_SINGLE) {
        // 如果master_process off那么就不是master进程
        // ngx_process_cycle.c
        ngx_single_process_cycle(cycle);

    } else {
        // ngx_process_cycle.c
        // 启动worker进程,数量由配置决定,即worker_processes指令
        // 核心操作是sigsuspend,暂时挂起进程,不占用CPU,只有收到信号时才被唤醒
        ngx_master_process_cycle(cycle);
    }

    // 只有退出无限循环才会走到这里,进程结束
    return 0;
}
Esempio n. 12
0
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;

    ngx_debug_init();

    if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }
    //获取参数和配置参数,比如命令是nginx -v 那么ngx_show_version就设置为1
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

    if (ngx_show_version) {
        ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED);

        if (ngx_show_help) {
            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;
    //初始化nginx环境的当前时间
    ngx_time_init();

#if (NGX_PCRE)
    ngx_regex_init();
#endif
    //master pid, 获取当前进程ID
    ngx_pid = ngx_getpid();
    // 初始化日志,如打开日志文件
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log); //是否开启了ssl,如果开启在这里进行初始化
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;
    ngx_cycle = &init_cycle;
    // 为cycle创建一个1024B的内存池
    init_cycle.pool = ngx_create_pool(1024, log);
    if (init_cycle.pool == NULL) {
        return 1;
    }
    // 将命令行参数保存到ngx_os_argv、ngx_argc以及ngx_argv这几个全局的变量中。
    // 这算是一个备份存储,方便以后master进程做热代码替换之用。
    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
        return 1;
    }
    // 初始化init_cycle中的一些如: conf_file,prefix,conf_prefix等字段
    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }

    // 完成操作系统的一些信息获取,如内存页面大小、系统限制资源,ngx_pagesize,ngx_cacheline_size,最大连接数ngx_max_sockets等
    // 所有的这些资源都将会被保存在对应的全局变量中,因此后续访问将会很便利。
    if (ngx_os_init(log) != NGX_OK) {// 这个ngx_os_init在不同操作系统调用不同的函数
        return 1;
    }

    /*
     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
     */
    // 初始化一个做循环冗余校验的表,由此可以看出后续的循环冗余校验将采用高效的查表法。
    if (ngx_crc32_table_init() != NGX_OK) {
        return 1;
    }

    // 通过环境变量NGINX完成socket的继承,继承来的socket将会放到init_cycle的listening数组中。
    // 在NGINX环境变量中,每个socket中间用冒号或分号隔开。完成继承同时设置全局变量ngx_inherited为1。
    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }
    // 计算模块个数,并且设置各个模块顺序(索引)
    // 这里面的ngx_modules会有非常多的模块,编译后在objs下面会生成一个ngx_modules.c文件,里边列出了所有使用的模块
    // 默认有44个模块
    ngx_max_module = 0;
    for (i = 0; ngx_modules[i]; i++) {
        ngx_modules[i]->index = ngx_max_module++;
    }
    // 对ngx_cycle结构进行初始化,这里是nginx启动核心之处, 会将很多东西放在init_cycle中
    // 详细见ngx_cycle.c中的 ngx_init_cycle方法
    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;
    }
    // 检查是否有设置信号处理,如有,进入ngx_signal_process处理
    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)
    // 注册一堆信号处理程序,需要注册的信号及相应的信号处理函数被放在一个类型为ngx_signal_t的数组signals中。
    // 数组定义在src/os/unix/ngx_process.c中。ngx_signal_t结构类型定义了信号值,信号名字,信号对应动作名以及信号处理函数。
    if (ngx_init_signals(cycle->log) != NGX_OK) {
        return 1;
    }
    // ngx_daemon肯定就是用来实现守护进程的函数了, 有需要写server程序的,可以直接copy这段代码实现守护进程。
    // 代码实现位于 ./src/os/unix/ngx_daemon.c
    if (!ngx_inherited && ccf->daemon) {
        if (ngx_daemon(cycle->log) != NGX_OK) {
            return 1;
        }

        ngx_daemonized = 1;
    }

    if (ngx_inherited) {
        ngx_daemonized = 1;
    }

#endif
    // 玩过Nginx的人都知道,Nginx启动后有一个记录进程id的文件,这个文件里面就一个pid。
    // 原来这个pid就是在这个地方记录下来的。查看ngx_create_pidfile函数可以看到这样的一行代码
    // 其中第一个参数为pid文件名称, 从核心配置文件中读取到的
    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); //多进程,master进程进入这个,这个函数在不同操作系统有不同实现。
    }

    return 0;
}
Esempio n. 13
0
//1.时间、正则、错误日志、ssl等初始化
//2.读入命令行参数
//3.OS相关初始化
//4.读入并解析配置
//5.核心模块初始化
//6.创建各种临时文件和目录
//7.创建共享内存
//8.打开listen的端口
//9.所有模块初始化
//10.启动worker进程
//全书内容可以在http://book.2cto.com/201304/19606.html中查看,可以直接复制注释
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();

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

    //获取参数和配置参数,比如命令是nginx -v 那么ngx_show_version就设置为1
    if (ngx_get_options(argc, argv) != NGX_OK) { //解析命令参数
        return 1;
    }

    if (ngx_show_version) {
        ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED);

        if (ngx_show_help) {
            ngx_write_stderr(
                "Usage: nginx [-?hvVtTq] [-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" //除了version外还可以显示操作系统和configure阶段等相关信息
                NGX_LINEFEED
                "  -t            : test configuration and exit" NGX_LINEFEED  //不启动nginx进程,只是测试配置文件是否有错误
                "  -T            : test configuration, dump it and exit"
                NGX_LINEFEED
                "  -q            : suppress non-error messages "
                "during configuration testing" NGX_LINEFEED //通过-t测试配置文件是否错误的时候,nginx -t -q可以把error级别以下的日志不输出的屏幕
                "  -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) {

#ifdef NGX_COMPILER
            ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED);
#endif

#if (NGX_SSL)
            if (SSLeay() == SSLEAY_VERSION_NUMBER) {
                ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
                                 NGX_LINEFEED);
            } else {
                ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
                                 " (running with ");
                ngx_write_stderr((char *) (uintptr_t)
                                 SSLeay_version(SSLEAY_VERSION));
                ngx_write_stderr(")" NGX_LINEFEED);
            }
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
            ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED);
#else
            ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED);
#endif
#endif

            ngx_write_stderr("configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
        }

        if (!ngx_test_config) {
            return 0;
        }
    }

    /* TODO */ ngx_max_sockets = -1;

    ngx_time_init(); //初始化nginx环境的当前时间

#if (NGX_PCRE)
    ngx_regex_init();
#endif

    ngx_pid = ngx_getpid();

    /*
    主进程启动的时候,此时还没有读取配置文件,即没有指定日志打印在哪里。nginx这时候虽然可以将一些出错内容或者结果输到标准输出,但是如果要记录一些系统初始化情况,
    socket监听状况,还是需要写到日志文件中去的。在nginx的main函数中,首先会调用ngx_log_init 函数,默认日志文件为:安装路径/logs/error.log,如果这个文件没有权限访问的话,
    会直接报错退出。在mian函数结尾处,在ngx_master_process_cycle函数调用之前,会close掉这个日志文件。
     */
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    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;
    }

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

        if (ngx_dump_config) {
            cd = cycle->config_dump.elts;

            for (i = 0; i < cycle->config_dump.nelts; i++) {

                ngx_write_stdout("# configuration file ");
                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
                                    cd[i].name.len);
                ngx_write_stdout(":" NGX_LINEFEED);

                b = cd[i].buffer;

                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
                ngx_write_stdout(NGX_LINEFEED);
            }
        }

        return 0;
    }

    /*
    如果hginx.conf中配置为单进程工作模式,这时将会调用ngx_single_process_cycle方法进入单迸程工作模式。
    */
    if (ngx_signal) { //加了-S参数
        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) { //在这里会把进程模式设置为MASTER模式
        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 (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        return 1;
    }

    if (log->file->fd != ngx_stderr) {
        //前面的log = ngx_log_init(ngx_prefix);
        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 { //一般都是走到这里,master方式
        ngx_master_process_cycle(cycle);

    }

    return 0;
}
Esempio n. 14
0
int ngx_cdecl
main(int argc, char *const *argv)
{
    char             *p;
    ssize_t           n;
    ngx_int_t         i;
    ngx_log_t        *log;
    ngx_cycle_t      *cycle, init_cycle;
    ngx_core_conf_t  *ccf;

#if (NGX_FREEBSD)
    ngx_debug_init();
#endif

    /* TODO */ ngx_max_sockets = -1;

    ngx_time_init();

#if (NGX_PCRE)
    ngx_regex_init();
#endif

    ngx_pid = ngx_getpid();

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

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

    /* init_cycle->log is required for signal handlers and ngx_getopt() */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    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_getopt(&init_cycle, argc, ngx_argv) != NGX_OK) {
        return 1;
    }

    if (ngx_show_version) {

        p = "nginx version: " NGINX_VER CRLF;
        n = sizeof("nginx version: " NGINX_VER CRLF) - 1;

        if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
            return 1;
        }

        if (ngx_show_configure) {
#ifdef NGX_COMPILER
            p = "built by " NGX_COMPILER CRLF;
            n = sizeof("built by " NGX_COMPILER CRLF) - 1;

            if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
                return 1;
            }
#endif

            p = "configure arguments:" NGX_CONFIGURE CRLF;
            n = sizeof("configure arguments:" NGX_CONFIGURE CRLF) - 1;

            if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
                return 1;
            }
        }

        if (!ngx_test_config) {
            return 0;
        }
    }

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

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

    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_error(NGX_LOG_EMERG, log, 0,
                          "the configuration file %s test failed",
                          init_cycle.conf_file.data);
        }

        return 1;
    }

    if (ngx_test_config) {
        ngx_log_error(NGX_LOG_INFO, log, 0,
                      "the configuration file %s was tested successfully",
                      cycle->conf_file.data);
        return 0;
    }

    ngx_os_status(cycle->log);

    ngx_cycle = cycle;

    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    ngx_process = ccf->master ? NGX_PROCESS_MASTER : NGX_PROCESS_SINGLE;

#if (NGX_WIN32)

#if 0

    TODO:

    if (ccf->run_as_service) {
        if (ngx_service(cycle->log) != NGX_OK) {
            return 1;
        }

        return 0;
    }
#endif

#else

    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_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

#endif

    if (ngx_process == NGX_PROCESS_MASTER) {
        ngx_master_process_cycle(cycle);

    } else {
        ngx_single_process_cycle(cycle);
    }

    return 0;
}
Esempio n. 15
0
/*nignx程序入口*/
int ngx_cdecl
main(int argc, char *const *argv)
{
    ngx_int_t         i;  				 //nignx定义的整形
    ngx_log_t        *log;  			 //nginx定义的长整形
    ngx_cycle_t      *cycle, init_cycle; //struct ngx_cycle_s 结构
    ngx_core_conf_t  *ccf;               //

    ngx_debug_init();                   //只是空的定义在unix下 

	/*nginx错误信息初始化,涉及内存分配*/
    if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }

	/*获取nginx启动参数*/
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

	/*程序参数显示版本号和帮助信息*/
    if (ngx_show_version) {
        ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED);

        if (ngx_show_help) {
            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) {

#ifdef NGX_COMPILER      
            ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED);
#endif

#if (NGX_SSL)
            if (SSLeay() == SSLEAY_VERSION_NUMBER) {
                ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
                                 NGX_LINEFEED);
            } else {
                ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
                                 " (running with ");
                ngx_write_stderr((char *) (uintptr_t)
                                 SSLeay_version(SSLEAY_VERSION));
                ngx_write_stderr(")" NGX_LINEFEED);
            }
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
            ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED);
#else
            ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED);
#endif
#endif

            ngx_write_stderr("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();             //获得进程ID

	/*初始化日志*/
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    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;
    }

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

	/*nginx模块列表生成,make生成的*/
    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

	/*创建记录进程ID文件*/
    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

    if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        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;
}
Esempio n. 16
0
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;

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

//get options input on start up
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

    if (ngx_show_version) {
        ngx_log_stderr(0, "nginx version: " NGINX_VER);

        if (ngx_show_help) {
            ngx_log_stderr(0,
                "Usage: nginx [-?hvVtq] [-s signal] [-c filename] "
                             "[-p prefix] [-g directives]" CRLF CRLF
                "Options:" CRLF
                "  -?,-h         : this help" CRLF
                "  -v            : show version and exit" CRLF
                "  -V            : show version and configure options then exit"
                                   CRLF
                "  -t            : test configuration and exit" CRLF
                "  -q            : suppress non-error messages "
                                   "during configuration testing" CRLF
                "  -s signal     : send signal to a master process: "
                                   "stop, quit, reopen, reload" CRLF
#ifdef NGX_PREFIX
                "  -p prefix     : set prefix path (default: "
                                   NGX_PREFIX ")" CRLF
#else
                "  -p prefix     : set prefix path (default: NONE)" CRLF
#endif
                "  -c filename   : set configuration file (default: "
                                   NGX_CONF_PATH ")" CRLF
                "  -g directives : set global directives out of configuration "
                                   "file" CRLF
                );
        }

        if (ngx_show_configure) {
#ifdef NGX_COMPILER
            ngx_log_stderr(0, "built by " NGX_COMPILER);
#endif
#if (NGX_SSL)
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
            ngx_log_stderr(0, "TLS SNI support enabled");
#else
            ngx_log_stderr(0, "TLS SNI support disabled");
#endif
#endif
            ngx_log_stderr(0, "configure arguments:" NGX_CONFIGURE);
        }

        if (!ngx_test_config) {
            return 0;
        }
    }

#if (NGX_FREEBSD)
    ngx_debug_init();
#endif

    /* TODO */ ngx_max_sockets = -1;

//调用ngx_time_init()初始化并更新时间
    ngx_time_init();

#if (NGX_PCRE)
    ngx_regex_init();
#endif

    ngx_pid = ngx_getpid();

//init log,调用ngx_log_init()初始化日志,如初始化全局变量ngx_prefix,打开日志文件ngx_log_file.fd
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */


//清零
    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;
    ngx_cycle = &init_cycle;

//创建内存池
    init_cycle.pool = ngx_create_pool(1024, log);
    if (init_cycle.pool == NULL) {
        return 1;
    }
//命令行参数保存到ngx_os_argv、ngx_argc以及ngx_argv这几个全局的变量中。这算是一个备份存储,方便以后master进程做热代码替换之用
    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
        return 1;
    }

//初始化ngx_cycle的prefix, conf_prefix, conf_file, conf_param等字段
    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }
//调用ngx_os_init()初始化系统相关变量,如内存页面大小ngx_pagesize,ngx_cacheline_size,最大连接数ngx_max_sockets等;
    if (ngx_os_init(log) != NGX_OK) {
        return 1;
    }

    /*
     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
     调用ngx_crc32_table_init()初始化CRC表(后续的CRC校验通过查表进行,效率高)
     */

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

/*
"	调用ngx_add_inherited_sockets()继承sockets;
o	解析环境变量NGINX_VAR="NGINX"中的sockets,并保存至ngx_cycle.listening数组;
o	设置ngx_inherited=1;
o	调用ngx_set_inherited_sockets()逐一对ngx_cycle.listening数组中的sockets进行设置

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

//初始化全局模块数组当中每个模块的index
//这个神秘的数组却是在自动编译的时候生成的,位于objs/ngx_modules.c文件中。这个循环的目的是清晰可见的--对所有模块进行索引编号,方便以后访问
    ngx_max_module = 0;
    for (i = 0; ngx_modules[i]; i++) {
        ngx_modules[i]->index = ngx_max_module++;
    }
//o	该初始化主要对ngx_cycle结构进行,核心!!
    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;
    }
//"	若有信号,则进入ngx_signal_process()处理
    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;
    }

//"	若无继承sockets,且设置了守护进程标识,则调用ngx_daemon()创建守护进程
    if (!ngx_inherited && ccf->daemon) {
        if (ngx_daemon(cycle->log) != NGX_OK) {
            return 1;
        }

        ngx_daemonized = 1;
    }

#endif
	//"	调用ngx_create_pidfile()创建进程记录文件
    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }
	//log file is OK
    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);	//master-slave模式这个过程里实现了master-worker模式的进程模型,也是生成环境下Nginx的常用模型
    }

    return 0;
}