void ngx_master_process_cycle(ngx_cycle_t *cycle) { u_long nev, ev, timeout; ngx_err_t err; ngx_int_t n; ngx_msec_t timer; ngx_uint_t live; HANDLE events[MAXIMUM_WAIT_OBJECTS]; ngx_sprintf((u_char *) ngx_master_process_event_name, "ngx_master_%s%Z", ngx_unique); if (ngx_process == NGX_PROCESS_WORKER) { ngx_worker_process_cycle(cycle, ngx_master_process_event_name); return; } ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "master started"); ngx_console_init(cycle); SetEnvironmentVariable("ngx_unique", ngx_unique); ngx_master_process_event = CreateEvent(NULL, 1, 0, ngx_master_process_event_name); if (ngx_master_process_event == NULL) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "CreateEvent(\"%s\") failed", ngx_master_process_event_name); exit(2); } if (ngx_create_signal_events(cycle) != NGX_OK) { exit(2); } ngx_sprintf((u_char *) ngx_cache_manager_mutex_name, "ngx_cache_manager_mutex_%s%Z", ngx_unique); ngx_cache_manager_mutex = CreateMutex(NULL, 0, ngx_cache_manager_mutex_name); if (ngx_cache_manager_mutex == NULL) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "CreateMutex(\"%s\") failed", ngx_cache_manager_mutex_name); exit(2); } events[0] = ngx_stop_event; events[1] = ngx_quit_event; events[2] = ngx_reopen_event; events[3] = ngx_reload_event; ngx_close_listening_sockets(cycle); if (ngx_start_worker_processes(cycle, NGX_PROCESS_RESPAWN) == 0) { exit(2); } timer = 0; timeout = INFINITE; for ( ;; ) { nev = 4; for (n = 0; n < ngx_last_process; n++) { if (ngx_processes[n].handle) { events[nev++] = ngx_processes[n].handle; } } if (timer) { timeout = timer > ngx_current_msec ? timer - ngx_current_msec : 0; } ev = WaitForMultipleObjects(nev, events, 0, timeout); err = ngx_errno; ngx_time_update(); ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "master WaitForMultipleObjects: %ul", ev); if (ev == WAIT_OBJECT_0) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); if (ResetEvent(ngx_stop_event) == 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "ResetEvent(\"%s\") failed", ngx_stop_event_name); } if (timer == 0) { timer = ngx_current_msec + 5000; } ngx_terminate = 1; ngx_quit_worker_processes(cycle, 0); continue; } if (ev == WAIT_OBJECT_0 + 1) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "shutting down"); if (ResetEvent(ngx_quit_event) == 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "ResetEvent(\"%s\") failed", ngx_quit_event_name); } ngx_quit = 1; ngx_quit_worker_processes(cycle, 0); continue; } if (ev == WAIT_OBJECT_0 + 2) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); if (ResetEvent(ngx_reopen_event) == 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "ResetEvent(\"%s\") failed", ngx_reopen_event_name); } ngx_reopen_files(cycle, -1); ngx_reopen_worker_processes(cycle); continue; } if (ev == WAIT_OBJECT_0 + 3) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); if (ResetEvent(ngx_reload_event) == 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "ResetEvent(\"%s\") failed", ngx_reload_event_name); } cycle = ngx_init_cycle(cycle); if (cycle == NULL) { cycle = (ngx_cycle_t *) ngx_cycle; continue; } ngx_cycle = cycle; ngx_close_listening_sockets(cycle); if (ngx_start_worker_processes(cycle, NGX_PROCESS_JUST_RESPAWN)) { ngx_quit_worker_processes(cycle, 1); } continue; } if (ev > WAIT_OBJECT_0 + 3 && ev < WAIT_OBJECT_0 + nev) { ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "reap worker"); live = ngx_reap_worker(cycle, events[ev]); if (!live && (ngx_terminate || ngx_quit)) { ngx_master_process_exit(cycle); } continue; } if (ev == WAIT_TIMEOUT) { ngx_terminate_worker_processes(cycle); ngx_master_process_exit(cycle); } if (ev == WAIT_FAILED) { ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "WaitForMultipleObjects() failed"); continue; } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "WaitForMultipleObjects() returned unexpected value %ul", ev); } }
// http://www.xuebuyuan.com/557917.html // http://blog.csdn.net/lu_ming/article/details/5144427 // http://blog.csdn.net/lengzijian/article/details/7587740 void ngx_master_process_cycle(ngx_cycle_t *cycle) { char *title; u_char *p; size_t size; ngx_int_t i; ngx_uint_t n, sigio; sigset_t set; struct itimerval itv; ngx_uint_t live; ngx_msec_t delay; ngx_listening_t *ls; ngx_core_conf_t *ccf; // block these signals sigemptyset(&set); sigaddset(&set, SIGCHLD); sigaddset(&set, SIGALRM); sigaddset(&set, SIGIO); sigaddset(&set, SIGINT); sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } sigemptyset(&set); // set title = "master process" + argv[0] + argv[1] + ... size = sizeof(master_process); for (i = 0; i < ngx_argc; i++) { size += ngx_strlen(ngx_argv[i]) + 1; } title = ngx_pnalloc(cycle->pool, size); p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); for (i = 0; i < ngx_argc; i++) { *p++ = ' '; p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size); } ngx_setproctitle(title); // Start workers and cache_manager ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_new_binary = 0; delay = 0; sigio = 0; live = 1; for ( ;; ) { if (delay) { if (ngx_sigalrm) { sigio = 0; delay *= 2; ngx_sigalrm = 0; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "termination cycle: %d", delay); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = delay / 1000; itv.it_value.tv_usec = (delay % 1000 ) * 1000; if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend"); // sigsuspend() temporarily replaces the signal mask of the calling // process with the mask given by mask and then suspends the process // until delivery of a signal whose action is to invoke a // signal handler or to terminate a process. sigsuspend(&set); ngx_time_update(); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up, sigio %i", sigio); if (ngx_reap) { ngx_reap = 0; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); live = ngx_reap_children(cycle); } if (!live && (ngx_terminate || ngx_quit)) { ngx_master_process_exit(cycle); } // on SIGINT set ngx_terminate = 1 if (ngx_terminate) { if (delay == 0) { delay = 50; } if (sigio) { sigio--; continue; } sigio = ccf->worker_processes + 2 /* cache processes */; if (delay > 1000) { ngx_signal_worker_processes(cycle, SIGKILL); } else { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } continue; } if (ngx_quit) { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { if (ngx_close_socket(ls[n].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[n].addr_text); } } cycle->listening.nelts = 0; continue; } if (ngx_reconfigure) { ngx_reconfigure = 0; if (ngx_new_binary) { ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_noaccepting = 0; continue; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); cycle = ngx_init_cycle(cycle); if (cycle == NULL) { cycle = (ngx_cycle_t *) ngx_cycle; continue; } ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_JUST_RESPAWN); ngx_start_cache_manager_processes(cycle, 1); // Nginx won't guarantee the new workers will be ready to accept // new connections before sending shutdown signals to old workers. // If the new works takes more than 100ms to startup, then there is // a risk that the old workers are shutdown but new workers are still // not ready, as a result, new connections will be pending until a new // worker is ready to handle. /* allow new processes to start */ ngx_msleep(100); live = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } if (ngx_restart) { ngx_restart = 0; ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); live = 1; } if (ngx_reopen) { ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, ccf->user); ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_REOPEN_SIGNAL)); } if (ngx_change_binary) { ngx_change_binary = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary"); ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv); } if (ngx_noaccept) { ngx_noaccept = 0; ngx_noaccepting = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } } }
//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; }
// 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; }
/* * __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) { 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; }
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; }
// main()函数里调用,启动worker进程 // 监听信号 // 核心操作是sigsuspend,暂时挂起进程,不占用CPU,只有收到信号时才被唤醒 void ngx_master_process_cycle(ngx_cycle_t *cycle) { char *title; u_char *p; size_t size; ngx_int_t i; ngx_uint_t n, sigio; sigset_t set; struct itimerval itv; ngx_uint_t live; ngx_msec_t delay; ngx_listening_t *ls; ngx_core_conf_t *ccf; // 添加master进程关注的信号 sigemptyset(&set); sigaddset(&set, SIGCHLD); sigaddset(&set, SIGALRM); sigaddset(&set, SIGIO); sigaddset(&set, SIGINT); sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } sigemptyset(&set); // static u_char master_process[] = "master process"; // 计算master进程的名字 size = sizeof(master_process); // 加上命令行参数,注意使用的是nginx拷贝后的参数 for (i = 0; i < ngx_argc; i++) { size += ngx_strlen(ngx_argv[i]) + 1; } // 分配名字的内存 title = ngx_pnalloc(cycle->pool, size); if (title == NULL) { /* fatal */ exit(2); } // 拷贝字符串 p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); for (i = 0; i < ngx_argc; i++) { *p++ = ' '; p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size); } // 设置进程名 ngx_setproctitle(title); // 取core模块配置 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); // 启动worker进程,数量由配置决定,即worker_processes指令 // #define NGX_PROCESS_RESPAWN -3 ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); // cache进程 ngx_start_cache_manager_processes(cycle, 0); ngx_new_binary = 0; delay = 0; //延时的计数器 sigio = 0; live = 1; //是否有存活的子进程 // master进程的无限循环,只处理信号 // 主要调用ngx_signal_worker_processes()发送信号 // ngx_start_worker_processes()产生新子进程 for ( ;; ) { // 延时等待子进程关闭,每次进入加倍等待 if (delay) { if (ngx_sigalrm) { sigio = 0; delay *= 2; //延时加倍 ngx_sigalrm = 0; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "termination cycle: %d", delay); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = delay / 1000; itv.it_value.tv_usec = (delay % 1000 ) * 1000; // 系统调用,设置发送SIGALRM的时间间隔 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend"); // 核心操作是sigsuspend,暂时挂起进程,不占用CPU,只有收到信号时才被唤醒 // 收到SIGALRM就检查子进程是否都已经处理完了 sigsuspend(&set); // 更新一下时间 ngx_time_update(); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up, sigio %i", sigio); // 子进程可能发生了意外结束 // 在os/unix/ngx_process.c ngx_signal_handler()里设置 if (ngx_reap) { ngx_reap = 0; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); // 重新产生子进程 live = ngx_reap_children(cycle); } // 无存活子进程且收到stop/quit信号 if (!live && (ngx_terminate || ngx_quit)) { // 删除pid,模块清理,关闭监听端口 // 内部直接exit(0)退出 ngx_master_process_exit(cycle); } // 收到了-s stop,停止进程 if (ngx_terminate) { // 延时等待子进程关闭 if (delay == 0) { delay = 50; } if (sigio) { sigio--; continue; } sigio = ccf->worker_processes + 2 /* cache processes */; if (delay > 1000) { // 超时太多,直接发送SIGKILL杀死进程 // master进程调用,遍历ngx_processes数组,用kill发送信号 ngx_signal_worker_processes(cycle, SIGKILL); } else { // master进程调用,遍历ngx_processes数组,用kill发送信号 // 走到worker进程的ngx_signal_handler() // 然后再是ngx_worker_process_cycle()的ngx_terminate ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } // 等待SIGALRM信号,检查子进程是否都结束 continue; } // 收到了-s quit,关闭监听端口后再停止进程(优雅关闭) if (ngx_quit) { // master进程调用,遍历ngx_processes数组,用kill发送信号 // 走到worker进程的ngx_signal_handler() // 然后再是ngx_worker_process_cycle()的ngx_quit ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); // 关闭所有监听端口 ls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { if (ngx_close_socket(ls[n].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[n].addr_text); } } cycle->listening.nelts = 0; continue; } // 收到了-s reload重新配置 if (ngx_reconfigure) { ngx_reconfigure = 0; // 启动新的nginx二进制 if (ngx_new_binary) { // 启动worker进程,数量由配置决定,即worker_processes指令 // 调用时传递的是#define NGX_PROCESS_RESPAWN -3 ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_noaccepting = 0; continue; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); // nginx可执行程序不变,以当前cycle重新初始化 cycle = ngx_init_cycle(cycle); if (cycle == NULL) { cycle = (ngx_cycle_t *) ngx_cycle; continue; } ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); // 启动worker进程,数量由配置决定,即worker_processes指令 // 调用时传递的是#define NGX_PROCESS_JUST_RESPAWN -2 // 这样新启动的进程不会发送shutdown信号 ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_JUST_RESPAWN); ngx_start_cache_manager_processes(cycle, 1); /* allow new processes to start */ // 阻塞等待100毫秒 ngx_msleep(100); // 设置进程存活标志 live = 1; // 关闭原来的worker进程 // 新启动的进程不会发送shutdown信号 // master进程调用,遍历ngx_processes数组,用kill发送信号 // 走到worker进程的ngx_signal_handler() // 然后再是ngx_worker_process_cycle()的ngx_quit ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } if (ngx_restart) { ngx_restart = 0; // 启动worker进程,数量由配置决定,即worker_processes指令 // 调用时传递的是#define NGX_PROCESS_RESPAWN -3 ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); // 设置进程存活标志 live = 1; } if (ngx_reopen) { ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, ccf->user); ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_REOPEN_SIGNAL)); } if (ngx_change_binary) { ngx_change_binary = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary"); ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv); } if (ngx_noaccept) { ngx_noaccept = 0; ngx_noaccepting = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } } //master进程无限循环结束 }
// 启动后master进程在这个函数进入死循环 void ngx_master_process_cycle(ngx_cycle_t *cycle) { char *title; u_char *p; size_t size; ngx_int_t i; ngx_uint_t n, sigio; sigset_t set; struct itimerval itv; ngx_uint_t live; ngx_msec_t delay; ngx_listening_t *ls; ngx_core_conf_t *ccf; sigemptyset(&set); sigaddset(&set, SIGCHLD); sigaddset(&set, SIGALRM); sigaddset(&set, SIGIO); sigaddset(&set, SIGINT); sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); // 让master进程只有在sigsuspend()里才会捕捉参数set里的信号。 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } sigemptyset(&set); // 设置ps命令显示的进程标题 size = sizeof(master_process); for (i = 0; i < ngx_argc; i++) { size += ngx_strlen(ngx_argv[i]) + 1; } title = ngx_pnalloc(cycle->pool, size); p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); for (i = 0; i < ngx_argc; i++) { *p++ = ' '; p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size); } ngx_setproctitle(title); ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); // 启动worker进程 ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); // 配置文件配置了相关功能时打开cache manager或cache loader进程, ngx_start_cache_manager_processes(cycle, 0); ngx_new_binary = 0; delay = 0; sigio = 0; live = 1; for ( ;; ) { if (delay) { // 收到退出信号后会使用这个分支, // 作用是定时检查是否还有活跃子进程,如果没有就退出master进程 if (ngx_sigalrm) { sigio = 0; delay *= 2; ngx_sigalrm = 0; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "termination cycle: %d", delay); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = delay / 1000; itv.it_value.tv_usec = (delay % 1000 ) * 1000; if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend"); // 当没有收到信号时进程会在这个函数里休眠, 当收到信号后如果有信号处理函数先运行信号处理函数, // 然后向下运行。 sigsuspend(&set); // 更新记录当前时间的全局变量。 ngx_time_update(); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up, sigio %i", sigio); if (ngx_reap) { // master进程的子进程结束时,master进程收到SIGCHLD信号后,ngx_reap被置1。 ngx_reap = 0; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); live = ngx_reap_children(cycle); } if (!live && (ngx_terminate || ngx_quit)) { // 收到退出信号且已经没有活跃子进程后便退出 ngx_master_process_exit(cycle); } if (ngx_terminate) { // 收到SIGINT,SIGTERM信号后,直接关闭nginx, // 首先给子进程发送关闭信号,1秒还没有关完就强制关闭所有子进程 if (delay == 0) { delay = 50; } if (sigio) { sigio--; continue; } sigio = ccf->worker_processes + 2 /* cache processes */; if (delay > 1000) { ngx_signal_worker_processes(cycle, SIGKILL); } else { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } continue; } if (ngx_quit) { // 收到SIGQUIT信号后,优雅关闭Nginx, // 待所有worker进程将已经连接的请求处理完后在退出 ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { if (ngx_close_socket(ls[n].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[n].addr_text); } } cycle->listening.nelts = 0; continue; } if (ngx_reconfigure) { // 收到SIGHUP信号后,ngx_reconfigure在信号处理函数中被置1,执行让新配置文件生效的操作。 ngx_reconfigure = 0; if (ngx_new_binary) { // 在不重新载入配置文件的情况下启动工作进程。 ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_noaccepting = 0; continue; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); cycle = ngx_init_cycle(cycle); if (cycle == NULL) { cycle = (ngx_cycle_t *) ngx_cycle; continue; } ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_JUST_RESPAWN); ngx_start_cache_manager_processes(cycle, 1); /* allow new processes to start */ ngx_msleep(100); live = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } if (ngx_restart) { // 好像是平滑升级时,新起的nginx意外退出了,要在把之前nginx的工作进程在重新启动 ngx_restart = 0; ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); live = 1; } if (ngx_reopen) { // 重新打开日志文件 ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, ccf->user); ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_REOPEN_SIGNAL)); } if (ngx_change_binary) { // 启动新的nignx,使新旧nginx同时工作 ngx_change_binary = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary"); ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv); } if (ngx_noaccept) { // 收到sigwinch信号后优雅关闭所有子进程 ngx_noaccept = 0; ngx_noaccepting = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } } }
//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; }
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; /* 与OS相关的debug宏, linux平台下它什么也不做 */ 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 [-?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(); 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; } /* 执行热替换时,new master 从环境变量继承old master的监听套接口 */ if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } /* 模块在ngx_modules数组中的索引填入 index字段 */ ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; } /* 创建一个新的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); } 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); /* master模式 */ if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER; /* 设置当前进程为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; }
void ngx_master_process_cycle(ngx_cycle_t *cycle) { char *title; u_char *p; size_t size; ngx_int_t i; ngx_uint_t n, sigio; sigset_t set; struct itimerval itv; ngx_uint_t live; ngx_msec_t delay; ngx_listening_t *ls; ngx_core_conf_t *ccf; struct rlimit rlmt; sigemptyset(&set); sigaddset(&set, SIGCHLD); sigaddset(&set, SIGALRM); sigaddset(&set, SIGIO); sigaddset(&set, SIGINT); sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } sigemptyset(&set); size = sizeof(master_process); for (i = 0; i < ngx_argc; i++) { size += ngx_strlen(ngx_argv[i]) + 1; } title = ngx_pnalloc(cycle->pool, size); p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); for (i = 0; i < ngx_argc; i++) { *p++ = ' '; p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size); } ngx_setproctitle(title); ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); /* The directives such as "user", "rlimit_core", etc. should also be * effective on master process. Changed by Zimbra */ 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_ALERT, cycle->log, ngx_errno, "setrlimit(RLIMIT_NOFILE, %i) failed", ccf->rlimit_nofile); } } if (ccf->rlimit_core != NGX_CONF_UNSET) { 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_ALERT, cycle->log, ngx_errno, "setrlimit(RLIMIT_CORE, %O) 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_ALERT, cycle->log, ngx_errno, "setrlimit(RLIMIT_SIGPENDING, %i) failed", ccf->rlimit_sigpending); } } #endif if (geteuid() == 0) { 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); } } /* end change by Zimbra */ ngx_start_cache_manager_processes(cycle, 0); ngx_new_binary = 0; delay = 0; sigio = 0; live = 1; for ( ;; ) { if (delay) { if (ngx_sigalrm) { sigio = 0; delay *= 2; ngx_sigalrm = 0; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "termination cycle: %d", delay); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = delay / 1000; itv.it_value.tv_usec = (delay % 1000 ) * 1000; if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend"); sigsuspend(&set); ngx_time_update(); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up, sigio %i", sigio); if (ngx_reap) { ngx_reap = 0; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); live = ngx_reap_children(cycle); } if (!live && (ngx_terminate || ngx_quit)) { ngx_master_process_exit(cycle); } if (ngx_terminate) { if (delay == 0) { delay = 50; } if (sigio) { sigio--; continue; } sigio = ccf->worker_processes + 2 /* cache processes */; if (delay > 1000) { ngx_signal_worker_processes(cycle, SIGKILL); } else { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } continue; } if (ngx_quit) { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { if (ngx_close_socket(ls[n].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[n].addr_text); } } cycle->listening.nelts = 0; continue; } if (ngx_reconfigure) { ngx_reconfigure = 0; if (ngx_new_binary) { ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_noaccepting = 0; continue; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); cycle = ngx_init_cycle(cycle); if (cycle == NULL) { cycle = (ngx_cycle_t *) ngx_cycle; continue; } ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_JUST_RESPAWN); ngx_start_cache_manager_processes(cycle, 1); live = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } if (ngx_restart) { ngx_restart = 0; ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); live = 1; } if (ngx_reopen) { ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, ccf->user); ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_REOPEN_SIGNAL)); } if (ngx_change_binary) { ngx_change_binary = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary"); ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv); } if (ngx_noaccept) { ngx_noaccept = 0; ngx_noaccepting = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } } }
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赋值给全局变量ngx_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; } /* * 新版本master进程通过ngx_add_inherited_sockets方法由环境变量读取平滑升级信息,并对 * 旧版本Nginx服务监听的句柄做继承处理 */ if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } if (ngx_preinit_modules() != NGX_OK) { return 1; } /* 重要 * 读取配置并初始化各个模块 */ 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; }
void ngx_master_process_cycle(ngx_cycle_t *cycle) { char *title; u_char *p; size_t size; ngx_int_t i; ngx_uint_t n; sigset_t set; struct itimerval itv; ngx_uint_t live; ngx_msec_t delay; ngx_listening_t *ls; ngx_core_conf_t *ccf; sigemptyset(&set); sigaddset(&set, SIGCHLD); sigaddset(&set, SIGALRM); sigaddset(&set, SIGIO); sigaddset(&set, SIGINT); sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } sigemptyset(&set); size = sizeof(master_process); for (i = 0; i < ngx_argc; i++) { size += ngx_strlen(ngx_argv[i]) + 1; } title = ngx_pnalloc(cycle->pool, size); p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); for (i = 0; i < ngx_argc; i++) { *p++ = ' '; p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size); } ngx_setproctitle(title); ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_new_binary = 0; delay = 0; live = 1; for ( ;; ) { if (delay) { if (ngx_sigalrm) { delay *= 2; ngx_sigalrm = 0; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "termination cycle: %d", delay); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = delay / 1000; itv.it_value.tv_usec = (delay % 1000 ) * 1000; if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend"); sigsuspend(&set); ngx_time_update(0, 0); ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up"); if (ngx_reap) { ngx_reap = 0; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); live = ngx_reap_children(cycle); } if (!live && (ngx_terminate || ngx_quit)) { ngx_master_process_exit(cycle); } if (ngx_terminate) { if (delay == 0) { delay = 50; } if (delay > 1000) { ngx_signal_worker_processes(cycle, SIGKILL); } else { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } continue; } if (ngx_quit) { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { if (ngx_close_socket(ls[n].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[n].addr_text); } } cycle->listening.nelts = 0; continue; } if (ngx_reconfigure) { ngx_reconfigure = 0; if (ngx_new_binary) { ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_noaccepting = 0; continue; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); cycle = ngx_init_cycle(cycle); if (cycle == NULL) { cycle = (ngx_cycle_t *) ngx_cycle; continue; } ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_JUST_RESPAWN); ngx_start_cache_manager_processes(cycle, 1); live = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } if (ngx_restart) { ngx_restart = 0; ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); live = 1; } if (ngx_reopen) { ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, ccf->user); ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_REOPEN_SIGNAL)); } if (ngx_change_binary) { ngx_change_binary = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary"); ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv); } if (ngx_noaccept) { ngx_noaccept = 0; ngx_noaccepting = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } } }
// main()函数里调用,仅启动一个进程,没有fork // master_process off; void ngx_single_process_cycle(ngx_cycle_t *cycle) { ngx_uint_t i; if (ngx_set_environment(cycle, NULL) == NULL) { /* fatal */ exit(2); } // 调用所有模块的init_process,即进程启动时hook for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_process) { if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { /* fatal */ exit(2); } } } // 无限循环,对外提供服务 // ngx_signal_handler处理unix信号 // 收到信号后设置ngx_quit/ngx_sigalrm/ngx_reconfigue等全局变量 // 由无限循环检查这些变量再处理 for ( ;; ) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); // 处理事件的核心函数, event模块里 // 处理socket读写事件和定时器事件 // 获取负载均衡锁,监听端口接受连接 // 调用epoll模块的ngx_epoll_process_events // 然后处理超时事件和在延后队列里的所有事件 // nginx大部分的工作量都在这里 ngx_process_events_and_timers(cycle); // 检查是否处于退出状态 // 这里不使用ngx_exiting变量,直接关闭端口退出 if (ngx_terminate || ngx_quit) { // 所有模块的退出hook for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->exit_process) { ngx_modules[i]->exit_process(cycle); } } // 删除pid,模块清理,关闭监听端口 // 内部直接exit(0)退出 ngx_master_process_exit(cycle); } // 重新配置,以当前cycle重新初始化,即reload if (ngx_reconfigure) { ngx_reconfigure = 0; //标志量清零 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); // 以当前cycle重新初始化 cycle = ngx_init_cycle(cycle); if (cycle == NULL) { cycle = (ngx_cycle_t *) ngx_cycle; continue; } ngx_cycle = cycle; } // 重新打开所有文件 if (ngx_reopen) { ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, (ngx_uid_t) -1); } } // 无限循环,对外提供服务 }
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("Tengine version: " TENGINE_VER " (" NGINX_VER ")" NGX_LINEFEED); if (ngx_show_help) { ngx_write_stderr( "Usage: nginx [-?hvmVtdq] [-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 " -m : show all modules and exit" NGX_LINEFEED " -l : show all directives and exit" NGX_LINEFEED " -V : show version, modules and configure options " "then exit" NGX_LINEFEED " -t : test configuration and exit" NGX_LINEFEED " -d : dump 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 && !ngx_show_modules && !ngx_show_directives) { 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_show_modules || ngx_show_directives) { return 0; } if (ngx_dump_config) { 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_open_pipes(cycle) == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "can not open pipes"); return 1; } 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; }
void ngx_master_process_cycle(ngx_cycle_t *cycle) { char *title; u_char *p; size_t size; ngx_int_t i; ngx_uint_t n, sigio; sigset_t set; struct itimerval itv; ngx_uint_t live; ngx_msec_t delay; ngx_listening_t *ls; ngx_core_conf_t *ccf; //屏蔽一系列信号,防止被打扰 sigemptyset(&set); sigaddset(&set, SIGCHLD); sigaddset(&set, SIGALRM); sigaddset(&set, SIGIO); sigaddset(&set, SIGINT); sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } sigemptyset(&set); // master_process 静态数组。参考本页 size = sizeof(master_process); for (i = 0; i < ngx_argc; i++) { size += ngx_strlen(ngx_argv[i]) + 1; } title = ngx_pnalloc(cycle->pool, size); p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); for (i = 0; i < ngx_argc; i++) { *p++ = ' '; p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size); } ngx_setproctitle(title); //master进程获取core模块配置,ccf中有要创建多少个worker的设定 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); //启动worker,这时已经有了worker进程 // NGX_PROCESS_RESPAWN 表示重新生成子进程 ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); //创建有关cache的子进程 ngx_new_binary = 0; delay = 0; sigio = 0; live = 1; for ( ;; ) { //delay用来等待子进程退出的时间,由于我们接受到SIGINT信号后,我们需要先发送信号给子进程, //而子进程的退出需要一定的时间,超时时如果子进程已退出,我们父进程就直接退出, //否则发送sigkill信号给子进程(强制退出),然后再退出。 if (delay) { if (ngx_sigalrm) { sigio = 0; delay *= 2; ngx_sigalrm = 0; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "termination cycle: %d", delay); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = delay / 1000; itv.it_value.tv_usec = (delay % 1000 ) * 1000; //设置定时器 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend"); //延时,等待信号 sigsuspend(&set); //调用这个将master进程挂起来 ngx_time_update(); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up, sigio %i", sigio); //ngx_reap为1,说明有子进程已经退出 if (ngx_reap) { ngx_reap = 0; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); //这个里面处理退出的子进程(有的worker异常退出,这时我们就需要重启这个worker ),如果所有子进程都退出则会返回0. live = ngx_reap_children(cycle); } //如果没有存活的子进程,并且收到了ngx_terminate或者ngx_quit信号,则master退出。 if (!live && (ngx_terminate || ngx_quit)) { ngx_master_process_exit(cycle); } //收到了sigint信号 if (ngx_terminate) { //设置延时 if (delay == 0) { delay = 50; } if (sigio) { sigio--; continue; } sigio = ccf->worker_processes + 2 /* cache processes */; if (delay > 1000) { //如果超时,则强制杀死worker ngx_signal_worker_processes(cycle, SIGKILL); } else { //负责发送sigint给worker,让它退出 ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } continue; } //收到quit信号 if (ngx_quit) { //发送给worker quit信号 ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { if (ngx_close_socket(ls[n].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[n].addr_text); } } cycle->listening.nelts = 0; continue; } //收到需要reconfig的信号 if (ngx_reconfigure) { ngx_reconfigure = 0; //判断是否热代码替换后的新的代码还在运行中(也就是还没退出当前的master)。如果还在运行中,则不需要重新初始化config if (ngx_new_binary) { ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_noaccepting = 0; continue; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); //重新初始化config,并重新启动新的worker cycle = ngx_init_cycle(cycle); if (cycle == NULL) { cycle = (ngx_cycle_t *) ngx_cycle; continue; } ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_JUST_RESPAWN); ngx_start_cache_manager_processes(cycle, 1); live = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } if (ngx_restart) { ngx_restart = 0; ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); live = 1; } //重新打开 if (ngx_reopen) { ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, ccf->user); ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_REOPEN_SIGNAL)); } //热代码替换 if (ngx_change_binary) { ngx_change_binary = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary"); //进行热代码替换,这里是调用execve来执行新的代码 ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv); } //接受到停止accept连接,其实也就是worker退出(有区别的是,这里master不需要退出) if (ngx_noaccept) { ngx_noaccept = 0; ngx_noaccepting = 1; //给worker发送信号 ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } } }
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; 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; }