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; }
//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; }
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; }
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; }
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; }
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; }
/* * __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; }
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; }
// 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; }
//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; }
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; }
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; }
//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; }
/*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; }
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; }