//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) { //读取服务器启动时后跟的参数,根据参数来设置一些全局变量(例如有-v时,设置 //ngx_show_version=1),从而来控制后面的执行流程 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; }