ngx_shm_zone_t * ngx_http_get_shm_zone(ngx_str_t *shm_name_t) { ngx_shm_zone_t **zone; size_t i; zone = g_shm_dict_list->elts; if (g_shm_dict_list == NULL || zone == NULL) { return NULL; } for (i = 0; i < g_shm_dict_list->nelts; i++) { if( shm_name_t->len == 0 && i == 0) { ngx_log_error(NGX_LOG_DEBUG, ((ngx_shm_dict_ctx_t *)(zone[i]->data))->log, 0, "[ah_shm_zone] process=[%d] get_shm_zone default name is %V \n", ngx_getpid(),&zone[i]->shm.name); return zone[i]; } if ( ngx_strcmp(shm_name_t->data, zone[i]->shm.name.data) == 0) { ngx_log_error(NGX_LOG_DEBUG, ((ngx_shm_dict_ctx_t *)(zone[i]->data))->log, 0, "[ah_shm_zone] process=[%d] get_shm_zone name is %V \n", ngx_getpid(),shm_name_t); return zone[i]; } } return NULL; }
/** * 上下文初始化 */ int TestContext::ctx_init(ngx_cycle_t* cycle) { test_config_t* cfg = &this->m_config; this->m_cycle = cycle; this->m_mysql_pool = mysql_pool_new(cfg->mysql_config.conns, &cfg->mysql_config); NLOG_INFO("[%d] mysql_pool: %p", ngx_getpid(), this->m_mysql_pool); #define SQL_CREATE_TBL "drop table if exists ngx_test; "\ "create table ngx_test(`key` varchar(32) primary key,value int default 0); "\ "insert into ngx_test values('testkey', 0);" int ret = 0; MYSQL* mysql = this->mysql_get(); if(mysql == NULL){ NLOG_ERROR("get mysql connection failed!"); ret = ERRNO_SYSTEM; return ret; } NLOG_INFO("init ngx_test table!"); ret = mysql_queryex(mysql, SQL_CREATE_TBL); NLOG_INFO("init ngx_test table ret:%d", ret); if(ret == 0){ mysql_free_all_result(mysql); }else{ NLOG_ERROR("init table failed!ret:%d, sql:[%s]", ret, SQL_CREATE_TBL); ret = ERRNO_SYSTEM; } // 在Init中取得的链接必须关闭掉,因为这个链接不是非阻塞的。 this->mysql_close(mysql); return NGX_OK; }
ngx_int_t ngx_daemon(ngx_log_t *log) { int fd; switch (fork()) { case -1: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed"); return NGX_ERROR; case 0: break; default: exit(0); } ngx_parent = ngx_pid; ngx_pid = ngx_getpid(); if (setsid() == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed"); return NGX_ERROR; } umask(0); fd = open("/dev/null", O_RDWR); if (fd == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "open(\"/dev/null\") failed"); return NGX_ERROR; } if (dup2(fd, STDIN_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed"); return NGX_ERROR; } if (dup2(fd, STDOUT_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed"); return NGX_ERROR; } #if 0 if (dup2(fd, STDERR_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed"); return NGX_ERROR; } #endif if (fd > STDERR_FILENO) { if (close(fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed"); return NGX_ERROR; } } return NGX_OK; }
/*创建守护进程,具体创建方法可以参考《unix环境高级编程》*/ ngx_int_t ngx_daemon(ngx_log_t *log) { int fd; switch (fork()) { case -1: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed"); return NGX_ERROR; case 0: //子进程作为守护进程 break; default: exit(0); //父进程退出 } ngx_pid = ngx_getpid(); if (setsid() == -1) { //setsid创建一个新会话 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed"); return NGX_ERROR; } umask(0); //打开文件/dev/null,使得其拥有守护进程的0,1,2。这样防止守护进程在终端设备上显示输出 fd = open("/dev/null", O_RDWR); if (fd == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "open(\"/dev/null\") failed"); return NGX_ERROR; } if (dup2(fd, STDIN_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed"); return NGX_ERROR; } if (dup2(fd, STDOUT_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed"); return NGX_ERROR; } #if 0 if (dup2(fd, STDERR_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed"); return NGX_ERROR; } #endif if (fd > STDERR_FILENO) { if (close(fd) == -1) { //关闭不需要的文件描述符 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed"); return NGX_ERROR; } } return NGX_OK; }
ngx_int_t ngx_http_shmtest_init_process(ngx_cycle_t *cycle) { shmtest_main_conf_t* conf = (shmtest_main_conf_t*)ngx_get_conf(cycle->conf_ctx, ngx_http_shmtest_module); if(conf == NULL){ NLOG_INFO("conf is null!"); return 0; } printf("process [%d] inited!\n", ngx_getpid()); //多进程并发测试 int i; int64_t ret=0; for(i=0;i<10000;i++){ ngx_str_t key = ngx_string("test"); ngx_shmap_inc_int(conf->shmap, &key, 1, 0, &ret); } printf("process [%d] init ok! ret=%lld\n", ngx_getpid(), (long long)ret); return 0; }
static ngx_int_t worker_process_write_out_stats(u_char *name, size_t len, void *val, void *para1, void *para2) { ngx_uint_t i; ngx_http_accounting_stats_t *stats; char output_buffer[1024]; ngx_uint_t status_code_buckets[10]; ngx_memzero(status_code_buckets, sizeof(status_code_buckets)); stats = (ngx_http_accounting_stats_t *)val; if (stats->nr_requests > 0) { for (i = 0; i < http_status_code_count; i++) { if (index_to_http_status_code_map[i] == NGX_HTTP_CLIENT_CLOSED_REQUEST) { status_code_buckets[9] += stats->http_status_code[i]; } else { ngx_uint_t bucket_idx = index_to_http_status_code_map[i] / 100; status_code_buckets[bucket_idx] += stats->http_status_code[i]; } stats->http_status_code[i] = 0; } } else { // no requests, let's not emit any stats! return NGX_OK; } sprintf(output_buffer, "%i|%ld|%ld|%s|%ld|%ld|%ld|%lu|%lu|%lu|%lu|%lu|%lu", ngx_getpid(), ngx_http_accounting_old_time, ngx_http_accounting_new_time, name, stats->nr_requests, stats->bytes_in, stats->bytes_out, stats->total_latency_ms / (stats->nr_requests > 0 ? stats->nr_requests : 1), stats->upstream_total_latency_ms / (stats->nr_requests > 0 ? stats->nr_requests : 1), status_code_buckets[2], status_code_buckets[4], status_code_buckets[5], status_code_buckets[9] ); stats->nr_requests = 0; stats->bytes_out = 0; stats->bytes_in = 0; stats->total_latency_ms = 0; stats->upstream_total_latency_ms = 0; syslog(LOG_INFO, "%s", output_buffer); return NGX_OK; }
ngx_int_t ngx_http_accounting_worker_process_init(ngx_cycle_t *cycle) { ngx_int_t rc; ngx_time_t *time; ngx_http_accounting_main_conf_t *amcf; amcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_accounting_module); if (!amcf->enable) { return NGX_OK; } init_http_status_code_map(); time = ngx_timeofday(); ngx_http_accounting_old_time = time->sec; ngx_http_accounting_new_time = time->sec; openlog((char *)ngx_http_accounting_title, LOG_NDELAY, LOG_SYSLOG); syslog(LOG_INFO, "pid:%i|Process:init", ngx_getpid()); rc = ngx_http_accounting_hash_init(&stats_hash, NGX_HTTP_ACCOUNTING_NR_BUCKETS, cycle->pool); if (rc != NGX_OK) { return rc; } ngx_memzero(&write_out_ev, sizeof(ngx_event_t)); write_out_ev.data = NULL; write_out_ev.log = cycle->log; write_out_ev.handler = worker_process_alarm_handler; srand(ngx_getpid()); ngx_add_timer(&write_out_ev, WORKER_PROCESS_TIMER_INTERVAL*(1000-rand()%200)); return NGX_OK; }
void ngx_http_accounting_worker_process_exit(ngx_cycle_t *cycle) { ngx_http_accounting_main_conf_t *amcf; amcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_accounting_module); if (!amcf->enable) { return; } worker_process_alarm_handler(NULL); syslog(LOG_INFO, "pid:%i|Process:exit", ngx_getpid()); }
ngx_int_t ngx_daemon(ngx_log_t *log) { int fd; switch (fork()) { case -1: printf("fork() failed"); return NGX_ERROR; case 0: /* child process */ break; default: /* parent process*/ exit(0); } ngx_pid = ngx_getpid(); if (setsid() == -1) { printf("setsid() failed"); return NGX_ERROR; } umask(0); fd = open("/dev/null", O_RDWR); if (fd == -1) { printf("open(\"/dev/null\") failed"); return NGX_ERROR; } if (dup2(fd, STDIN_FILENO) == -1) { printf("dup2(STDIN) failed"); return NGX_ERROR; } if (dup2(fd, STDOUT_FILENO) == -1) { printf("dup2(STDOUT) failed"); return NGX_ERROR; } if (fd > STDERR_FILENO) { if (close(fd) == -1) { printf("close() failed"); return NGX_ERROR; } } return NGX_OK; }
static ngx_int_t worker_process_write_out_stats(u_char *name, size_t len, void *val, void *para1, void *para2) { ngx_uint_t i; ngx_http_accounting_stats_t *stats; char temp_buffer[128]; char output_buffer[1024]; stats = (ngx_http_accounting_stats_t *)val; if (stats->nr_requests == 0) { return NGX_OK; } sprintf(output_buffer, "pid:%i|from:%ld|to:%ld|accounting_id:%s|requests:%ld|bytes_in:%ld|bytes_out:%ld|latency_ms:%lu|upstream_latency_ms:%lu", ngx_getpid(), ngx_http_accounting_old_time, ngx_http_accounting_new_time, name, stats->nr_requests, stats->bytes_in, stats->bytes_out, stats->total_latency_ms, stats->total_upstream_latency_ms ); stats->nr_requests = 0; stats->bytes_in = 0; stats->bytes_out = 0; stats->total_latency_ms = 0; stats->total_upstream_latency_ms = 0; for (i = 0; i < http_status_code_count; i++) { if(stats->http_status_code[i] > 0) { sprintf(temp_buffer, "|%ld:%ld", index_to_http_status_code_map[i], stats->http_status_code[i]); strcat(output_buffer, temp_buffer); stats->http_status_code[i] = 0; } } syslog(LOG_INFO, "%s", output_buffer); return NGX_OK; }
int ngx_shm_dict_handler_delete(ngx_shm_zone_t* zone_t, ngx_str_t *key) { int rc; ngx_shm_dict_ctx_t *ctx; ctx = zone_t->data; rc = ngx_shm_dict_delete(zone_t,key); ngx_log_error(NGX_LOG_DEBUG, ctx->log, 0, "[ah_shm_zone] process=[%d] operator=[%s] zone=[%V] key=[%V] " "rc=[%d]\n",ngx_getpid(),"del",&zone_t->shm.name,key,rc); return rc; }
int ngx_shm_dict_handler_flush_all(ngx_shm_zone_t* zone_t) { int rc; ngx_shm_dict_ctx_t *ctx; ctx = zone_t->data; rc = ngx_shm_dict_flush_all(zone_t); ngx_log_error(NGX_LOG_DEBUG, ctx->log, 0, "[ah_shm_zone] process=[%d] operator=[%s] zone=[%V] rc=[%d]\n", ngx_getpid(),"flush",&zone_t->shm.name,rc); return rc; }
int ngx_shm_dict_handler_set_exptime(ngx_shm_zone_t* zone_t, ngx_str_t* key, uint32_t exptime) { int rc; ngx_shm_dict_ctx_t *ctx; ctx = zone_t->data; rc = ngx_shm_dict_set_exptime(zone_t, key,exptime); ngx_log_error(NGX_LOG_DEBUG, ctx->log, 0, "[ah_shm_zone] process=[%d] operator=[%s] zone=[%V] key=[%V] " "exptime=[%d] rc=[%d]\n",ngx_getpid(),"set", &zone_t->shm.name,key,exptime,rc); return rc; }
static void ngx_error_signal_handler(int signo) { void *buffer; size_t size; ngx_log_t *log; ngx_signal_t *sig; struct sigaction sa; ngx_backtrace_conf_t *bcf; for (sig = ngx_backtrace_signals; sig->signo != 0; sig++) { if (sig->signo == signo) { break; } } bcf = (ngx_backtrace_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, ngx_backtrace_module); log = bcf->log ? bcf->log : ngx_cycle->log; ngx_log_error(NGX_LOG_ERR, log, 0, "nginx coredump by signal %d (%s)", signo, sig->signame); ngx_memzero(&sa, sizeof(struct sigaction)); sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); if (sigaction(signo, &sa, NULL) == -1) { ngx_log_error(NGX_LOG_ERR, log, ngx_errno, "sigaction(%s) failed", sig->signame); } if (bcf->max_stack_size == NGX_CONF_UNSET) { bcf->max_stack_size = NGX_BACKTRACE_DEFAULT_STACK_MAX_SIZE; } buffer = ngx_pcalloc(ngx_cycle->pool, sizeof(void *) * bcf->max_stack_size); if (buffer == NULL) { goto invalid; } size = backtrace(buffer, bcf->max_stack_size); backtrace_symbols_fd(buffer, size, log->file->fd); invalid: kill(ngx_getpid(), signo); }
int ngx_shm_dict_handler_incr_int(ngx_shm_zone_t* zone_t, ngx_str_t *key, int count, uint32_t exptime,int64_t* res) { int rc; ngx_shm_dict_ctx_t *ctx; ctx = zone_t->data; rc = ngx_shm_dict_inc_int(zone_t, key, count,0, res); ngx_log_error(NGX_LOG_DEBUG, ctx->log, 0, "[ah_shm_zone] process=[%d] operator=[%s] zone=[%V] key=[%V] " "count=[%d] exptime=[%d] rc=[%d]\n",ngx_getpid(),"incr", &zone_t->shm.name,key,count,exptime,rc); return rc; }
int ngx_shm_dict_handler_get(ngx_shm_zone_t *zone_t,ngx_str_t *key,ngx_str_t *value, uint32_t *exptime) { int rc; ngx_shm_dict_ctx_t *ctx; uint8_t value_type = SHM_STRING; ctx = zone_t->data; rc = ngx_shm_dict_get(zone_t, key,value,&value_type,exptime,0); ngx_log_error(NGX_LOG_DEBUG, ctx->log, 0, "[ah_shm_zone] process=[%d] operator=[%s] zone=[%V] key=[%V] " "value=[%V] exptime=[%d] rc=[%d]\n",ngx_getpid(),"get", &zone_t->shm.name,key,value,*exptime,rc); return rc; }
static ngx_int_t ngx_rtmp_stat_handler(ngx_http_request_t *r) { ngx_rtmp_stat_loc_conf_t *slcf; ngx_rtmp_core_main_conf_t *cmcf; ngx_rtmp_core_srv_conf_t **cscf; ngx_chain_t *cl, *l, **ll, ***lll; size_t n; off_t len; static u_char tbuf[NGX_TIME_T_LEN + 1]; static u_char nbuf[NGX_OFF_T_LEN + 1]; slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module); if (slcf->stat == 0) { return NGX_DECLINED; } cmcf = ngx_rtmp_core_main_conf; if (cmcf == NULL) { goto error; } cl = NULL; ll = &cl; lll = ≪ NGX_RTMP_STAT_L("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n"); if (slcf->stylesheet.len) { NGX_RTMP_STAT_L("<?xml-stylesheet type=\"text/xsl\" href=\""); NGX_RTMP_STAT_ES(&slcf->stylesheet); NGX_RTMP_STAT_L("\" ?>\r\n"); } NGX_RTMP_STAT_L("<rtmp>\r\n"); #ifdef NGINX_VERSION NGX_RTMP_STAT_L("<version>" NGINX_VERSION "</version>\r\n"); #endif #ifdef NGX_COMPILER NGX_RTMP_STAT_L("<compiler>" NGX_COMPILER "</compiler>\r\n"); #endif NGX_RTMP_STAT_L("<built>" __DATE__ " " __TIME__ "</built>\r\n"); NGX_RTMP_STAT_L("<pid>"); NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf), "%ui", (ngx_uint_t) ngx_getpid()) - nbuf); NGX_RTMP_STAT_L("</pid>\r\n"); NGX_RTMP_STAT_L("<uptime>"); NGX_RTMP_STAT(tbuf, ngx_snprintf(tbuf, sizeof(tbuf), "%T", ngx_cached_time->sec - start_time) - tbuf); NGX_RTMP_STAT_L("</uptime>\r\n"); NGX_RTMP_STAT_L("<naccepted>"); NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf), "%ui", ngx_rtmp_naccepted) - nbuf); NGX_RTMP_STAT_L("</naccepted>\r\n"); ngx_rtmp_stat_bw(r, lll, &ngx_rtmp_bw_in, &ngx_rtmp_bw_out); cscf = cmcf->servers.elts; for (n = 0; n < cmcf->servers.nelts; ++n, ++cscf) { ngx_rtmp_stat_server(r, lll, *cscf); } NGX_RTMP_STAT_L("</rtmp>\r\n"); len = 0; for (l = cl; l; l = l->next) { len += (l->buf->last - l->buf->pos); } ngx_str_set(&r->headers_out.content_type, "text/xml"); r->headers_out.content_length_n = len; r->headers_out.status = NGX_HTTP_OK; ngx_http_send_header(r); (*ll)->buf->last_buf = 1; return ngx_http_output_filter(r, cl); error: r->headers_out.status = NGX_HTTP_INTERNAL_SERVER_ERROR; r->headers_out.content_length_n = 0; return ngx_http_send_header(r); }
int ngx_cdecl main(int argc, char *const *argv) { ngx_int_t i; ngx_log_t *log; ngx_cycle_t *cycle, init_cycle; ngx_core_conf_t *ccf; ngx_debug_init(); if (ngx_strerror_init() != NGX_OK) { return 1; } if (ngx_get_options(argc, argv) != NGX_OK) { return 1; } if (ngx_show_version) { ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED); if (ngx_show_help) { ngx_write_stderr( "Usage: nginx [-?hvVtq] [-s signal] [-c filename] " "[-p prefix] [-g directives]" NGX_LINEFEED NGX_LINEFEED "Options:" NGX_LINEFEED " -?,-h : this help" NGX_LINEFEED " -v : show version and exit" NGX_LINEFEED " -V : show version and configure options then exit" NGX_LINEFEED " -t : test configuration and exit" NGX_LINEFEED " -q : suppress non-error messages " "during configuration testing" NGX_LINEFEED " -s signal : send signal to a master process: " "stop, quit, reopen, reload" NGX_LINEFEED #ifdef NGX_PREFIX " -p prefix : set prefix path (default: " NGX_PREFIX ")" NGX_LINEFEED #else " -p prefix : set prefix path (default: NONE)" NGX_LINEFEED #endif " -c filename : set configuration file (default: " NGX_CONF_PATH ")" NGX_LINEFEED " -g directives : set global directives out of configuration " "file" NGX_LINEFEED NGX_LINEFEED ); } if (ngx_show_configure) { ngx_write_stderr( #ifdef NGX_COMPILER "built by " NGX_COMPILER NGX_LINEFEED #endif #if (NGX_SSL) #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME "TLS SNI support enabled" NGX_LINEFEED #else "TLS SNI support disabled" NGX_LINEFEED #endif #endif "configure arguments:" NGX_CONFIGURE NGX_LINEFEED); } if (!ngx_test_config) { return 0; } } /* TODO */ ngx_max_sockets = -1; ngx_time_init(); #if (NGX_PCRE) ngx_regex_init(); #endif ngx_pid = ngx_getpid(); log = ngx_log_init(ngx_prefix); if (log == NULL) { return 1; } /* STUB */ #if (NGX_OPENSSL) ngx_ssl_init(log); #endif /* * init_cycle->log is required for signal handlers and * ngx_process_options() */ ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); init_cycle.log = log; ngx_cycle = &init_cycle; init_cycle.pool = ngx_create_pool(1024, log); if (init_cycle.pool == NULL) { return 1; } if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } if (ngx_os_init(log) != NGX_OK) { return 1; } /* * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() */ if (ngx_crc32_table_init() != NGX_OK) { return 1; } if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; } cycle = ngx_init_cycle(&init_cycle); if (cycle == NULL) { if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data); } return 1; } if (ngx_test_config) { if (!ngx_quiet_mode) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); } return 0; } if (ngx_signal) { return ngx_signal_process(cycle, ngx_signal); } ngx_os_status(cycle->log); ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER; } #if !(NGX_WIN32) if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; } if (!ngx_inherited && ccf->daemon) { if (ngx_daemon(cycle->log) != NGX_OK) { return 1; } ngx_daemonized = 1; } if (ngx_inherited) { ngx_daemonized = 1; } #endif if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } if (cycle->log->file->fd != ngx_stderr) { if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_set_stderr_n " failed"); return 1; } } if (log->file->fd != ngx_stderr) { if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed"); } } ngx_use_stderr = 0; if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); } return 0; }
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn) { u_long on; ngx_pid_t pid; ngx_int_t s; if (respawn >= 0) {//ngx_start_worker_processes-> NGX_PROCESS_RESPAWN ,表示要重新创建进程 s = respawn; } else {//得到当前有多少工作进程创建了ngx_last_process会不断增加的,当然可能有人死了 for (s = 0; s < ngx_last_process; s++) { if (ngx_processes[s].pid == -1) { break; } } if (s == NGX_MAX_PROCESSES) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "no more than %d processes can be spawned", NGX_MAX_PROCESSES); return NGX_INVALID_PID; } } if (respawn != NGX_PROCESS_DETACHED) {//NGX_PROCESS_DETACHED说明是热代码替换 //不是热代码替换 /* Solaris 9 still has no AF_LOCAL */ //创建socketpair,进程之间通信 if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1){ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "socketpair() failed while spawning \"%s\"", name); return NGX_INVALID_PID; } ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, "channel %d:%d", ngx_processes[s].channel[0], ngx_processes[s].channel[1]); //将socket对设置为非阻塞模式 if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_nonblocking_n " failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_nonblocking_n " failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } on = 1;//FIOASYNC 改变O_ASYNC 标志来打开或者关闭套接字的异步 IO 模式。 if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "ioctl(FIOASYNC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(F_SETOWN) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //close on exec, not on-fork, 意为如果对描述符设置了FD_CLOEXEC,使用execl执行的程序里, //此描述符被关闭,不能再使用它,但是在使用fork调用的子进程中,此描述符并不关闭,仍可使用。 if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //设置fork对socket对是在子进程依然可用的 if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } ngx_channel = ngx_processes[s].channel[1]; } else {//如果是热代码替换,不跟其他进程通信 ngx_processes[s].channel[0] = -1; ngx_processes[s].channel[1] = -1; } ngx_process_slot = s;//当前在处理这个 pid = fork();//fork子进程 switch (pid) { case -1: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fork() failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; case 0://子进程调用proc ngx_pid = ngx_getpid();//k getpid proc(cycle, data);//等于ngx_worker_process_cycle //子进程永远也从这回不来了,里面有exit break; default://父进程默认不干活 break; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid); ngx_processes[s].pid = pid; ngx_processes[s].exited = 0; if (respawn >= 0) { return pid; } //设置ngx_processes数组该项的信息 ngx_processes[s].proc = proc;//设置工作进程的处理函数ngx_worker_process_cycle,会fork之后调用的 ngx_processes[s].data = data; ngx_processes[s].name = name;//进程名字 ngx_processes[s].exiting = 0; switch (respawn) { case NGX_PROCESS_NORESPAWN: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 0; break; case NGX_PROCESS_JUST_SPAWN: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 1; ngx_processes[s].detached = 0; break; case NGX_PROCESS_RESPAWN: ngx_processes[s].respawn = 1; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 0; break; case NGX_PROCESS_JUST_RESPAWN: ngx_processes[s].respawn = 1; ngx_processes[s].just_spawn = 1; ngx_processes[s].detached = 0; break; case NGX_PROCESS_DETACHED: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 1; break; } if (s == ngx_last_process) { ngx_last_process++;//递增总进程数 } return pid; }
int ngx_cdecl main(int argc, char *const *argv) { ngx_int_t i; ngx_log_t *log; ngx_cycle_t *cycle, init_cycle; ngx_core_conf_t *ccf; ngx_debug_init(); // posix 系统上为空 // 把0到GX_SYS_NERR的strerror信息存到ngx_sys_errlist里 // 以后错误信息直接从这儿取 if (ngx_strerror_init() != NGX_OK) { return 1; } // 解析命令行 if (ngx_get_options(argc, argv) != NGX_OK) { return 1; } // 显示帮助信息 if (ngx_show_version) { ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED); if (ngx_show_help) { ngx_write_stderr( "Usage: nginx [-?hvVtq] [-s signal] [-c filename] " "[-p prefix] [-g directives]" NGX_LINEFEED NGX_LINEFEED "Options:" NGX_LINEFEED " -?,-h : this help" NGX_LINEFEED " -v : show version and exit" NGX_LINEFEED " -V : show version and configure options then exit" NGX_LINEFEED " -t : test configuration and exit" NGX_LINEFEED " -q : suppress non-error messages " "during configuration testing" NGX_LINEFEED " -s signal : send signal to a master process: " "stop, quit, reopen, reload" NGX_LINEFEED #ifdef NGX_PREFIX " -p prefix : set prefix path (default: " NGX_PREFIX ")" NGX_LINEFEED #else " -p prefix : set prefix path (default: NONE)" NGX_LINEFEED #endif " -c filename : set configuration file (default: " NGX_CONF_PATH ")" NGX_LINEFEED " -g directives : set global directives out of configuration " "file" NGX_LINEFEED NGX_LINEFEED ); } // 显示编译参数 if (ngx_show_configure) { ngx_write_stderr( #ifdef NGX_COMPILER "built by " NGX_COMPILER NGX_LINEFEED #endif #if (NGX_SSL) #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME "TLS SNI support enabled" NGX_LINEFEED #else "TLS SNI support disabled" NGX_LINEFEED #endif #endif "configure arguments:" NGX_CONFIGURE NGX_LINEFEED); } if (!ngx_test_config) { return 0; } } /* TODO */ ngx_max_sockets = -1; ngx_time_init(); // 初始化时钟 #if (NGX_PCRE) ngx_regex_init(); #endif ngx_pid = ngx_getpid(); log = ngx_log_init(ngx_prefix); // 初始化错误日志,打开错误日志文件 if (log == NULL) { return 1; } /* STUB */ #if (NGX_OPENSSL) ngx_ssl_init(log); #endif /* * init_cycle->log is required for signal handlers and ngx_process_options() */ ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); init_cycle.log = log; ngx_cycle = &init_cycle; init_cycle.pool = ngx_create_pool(1024, log); if (init_cycle.pool == NULL) { return 1; } // 把命令行参数保存在 os/unix/ngx_process.c:30:char **ngx_argv; if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } // 决定NGINX运行的目录 if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } if (ngx_os_init(log) != NGX_OK) { return 1; } /* * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() */ if (ngx_crc32_table_init() != NGX_OK) { return 1; } // 通过环境变量NGINX完成socket的继承,继承来的socket将会放到init_cycle的listening数组中。同时可以读取master进程传递的平滑升级信息等等 if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } //初始化所有模块的index信息,即对所有模块进行编号 //ngx_modules数却是在自动编译的时候生成的,位于objs/ngx_modules.c文件中 ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; } // 初始化重点都在这儿了 cycle = ngx_init_cycle(&init_cycle); if (cycle == NULL) { if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data); } return 1; } // nginx -t 测试配置文件 if (ngx_test_config) { if (!ngx_quiet_mode) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); } return 0; } // nginx -s if (ngx_signal) { return ngx_signal_process(cycle, ngx_signal); } ngx_os_status(cycle->log); ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER; } #if !(NGX_WIN32) if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; } if (!ngx_inherited && ccf->daemon) { if (ngx_daemon(cycle->log) != NGX_OK) { return 1; } ngx_daemonized = 1; } if (ngx_inherited) { ngx_daemonized = 1; } #endif if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } if (ngx_log_redirect_stderr(cycle) != NGX_OK) { return 1; } if (log->file->fd != ngx_stderr) { if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed"); } } ngx_use_stderr = 0; if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); } return 0; }
int ngx_cdecl main(int argc, char *const *argv) { ngx_int_t i; ngx_log_t *log; ngx_cycle_t *cycle, init_cycle; ngx_core_conf_t *ccf; #if !(NGX_WIN32) struct rlimit rlmt; #endif if (ngx_get_options(argc, argv) != NGX_OK) { return 1; } if (ngx_show_version) { ngx_log_stderr(0, "nginx version: " NGINX_VER); if (ngx_show_help) { ngx_log_stderr(0, "Usage: nginx [-?hvVt] [-s signal] [-c filename] " "[-p prefix] [-g directives]" CRLF CRLF "Options:" CRLF " -?,-h : this help" CRLF " -v : show version and exit" CRLF " -V : show version and configure options then exit" CRLF " -t : test configuration and exit" CRLF " -s signal : send signal to a master process: " "stop, quit, reopen, reload" CRLF #ifdef NGX_PREFIX " -p prefix : set prefix path (default: " NGX_PREFIX ")" CRLF #else " -p prefix : set prefix path (default: NONE)" CRLF #endif " -c filename : set configuration file (default: " NGX_CONF_PATH ")" CRLF " -g directives : set global directives out of configuration " "file" CRLF ); } if (ngx_show_configure) { #ifdef NGX_COMPILER ngx_log_stderr(0, "built by " NGX_COMPILER); #endif #if (NGX_SSL) #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME ngx_log_stderr(0, "TLS SNI support enabled"); #else ngx_log_stderr(0, "TLS SNI support disabled"); #endif #endif ngx_log_stderr(0, "configure arguments:" NGX_CONFIGURE); } if (!ngx_test_config) { return 0; } } #if (NGX_FREEBSD) ngx_debug_init(); #endif /* TODO */ ngx_max_sockets = -1; ngx_time_init(); #if (NGX_PCRE) ngx_regex_init(); #endif ngx_pid = ngx_getpid(); log = ngx_log_init(ngx_prefix); if (log == NULL) { return 1; } /* STUB */ #if (NGX_OPENSSL) ngx_ssl_init(log); #endif /* * init_cycle->log is required for signal handlers and * ngx_process_options() */ ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); init_cycle.log = log; ngx_cycle = &init_cycle; init_cycle.pool = ngx_create_pool(1024, log); if (init_cycle.pool == NULL) { return 1; } if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } if (ngx_os_init(log) != NGX_OK) { return 1; } /* * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() */ if (ngx_crc32_table_init() != NGX_OK) { return 1; } if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; } cycle = ngx_init_cycle(&init_cycle); if (cycle == NULL) { if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data); } return 1; } if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); return 0; } if (ngx_signal) { return ngx_signal_process(cycle, ngx_signal); } ngx_os_status(cycle->log); ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER; } #if !(NGX_WIN32) if (geteuid() == 0) { if (ccf->rlimit_nofile != NGX_CONF_UNSET) { rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile; rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile; if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setrlimit(RLIMIT_NOFILE, %i) failed", ccf->rlimit_nofile); } } if (ccf->rlimit_core != NGX_CONF_UNSET_SIZE) { rlmt.rlim_cur = (rlim_t) ccf->rlimit_core; rlmt.rlim_max = (rlim_t) ccf->rlimit_core; if (setrlimit(RLIMIT_CORE, &rlmt) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setrlimit(RLIMIT_CORE, %i) failed", ccf->rlimit_core); } } #ifdef RLIMIT_SIGPENDING if (ccf->rlimit_sigpending != NGX_CONF_UNSET) { rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending; rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending; if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setrlimit(RLIMIT_SIGPENDING, %i) failed", ccf->rlimit_sigpending); } } #endif if (setgid(ccf->group) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setgid(%d) failed", ccf->group); /* fatal */ exit(2); } if (initgroups(ccf->username, ccf->group) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "initgroups(%s, %d) failed", ccf->username, ccf->group); } if (setuid(ccf->user) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setuid(%d) failed", ccf->user); /* fatal */ exit(2); } } if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; } if (!ngx_inherited && ccf->daemon) { if (ngx_daemon(cycle->log) != NGX_OK) { return 1; } ngx_daemonized = 1; } #endif if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } if (cycle->log->file->fd != ngx_stderr) { if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_set_stderr_n " failed"); return 1; } } if (log->file->fd != ngx_stderr) { if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed"); } } ngx_use_stderr = 0; if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); } return 0; }
int ngx_cdecl main(int argc, char *const *argv) { ngx_int_t i; ngx_log_t *log; ngx_cycle_t *cycle, init_cycle; ngx_core_conf_t *ccf; ngx_debug_init(); if (ngx_strerror_init() != NGX_OK) { return 1; } if (ngx_get_options(argc, argv) != NGX_OK) { return 1; } /* TODO */ ngx_max_sockets = -1; ngx_time_init(); ngx_pid = ngx_getpid(); log = ngx_log_init(ngx_prefix); if (log == NULL) { return 1; } /* STUB */ /* * init_cycle->log is required for signal handlers and * ngx_process_options() */ ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); init_cycle.log = log; ngx_cycle = &init_cycle; init_cycle.pool = ngx_create_pool(1024, log); if (init_cycle.pool == NULL) { return 1; } if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } if (ngx_os_init(log) != NGX_OK) { return 1; } /* * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() */ if (ngx_crc32_table_init() != NGX_OK) { return 1; } if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; } cycle = ngx_init_cycle(&init_cycle); if (cycle == NULL) { if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data); } return 1; } if (ngx_test_config) { if (!ngx_quiet_mode) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); } return 0; } if (ngx_signal) { return ngx_signal_process(cycle, ngx_signal); } ngx_os_status(cycle->log); ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER; } // if (ngx_init_signals(cycle->log) != NGX_OK) { // return 1; // } // // if (!ngx_inherited && ccf->daemon) { // if (ngx_daemon(cycle->log) != NGX_OK) { // return 1; // } // // ngx_daemonized = 1; // } // // if (ngx_inherited) { // ngx_daemonized = 1; // } if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } if (ngx_log_redirect_stderr(cycle) != NGX_OK) { return 1; } if (log->file->fd != ngx_stderr) { if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed"); } } ngx_use_stderr = 0; // if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); // } else { // ngx_master_process_cycle(cycle); // } return 0; }
int ngx_cdecl main(int argc, char *const *argv) { ngx_buf_t *b; ngx_log_t *log; ngx_uint_t i; ngx_cycle_t *cycle, init_cycle; ngx_conf_dump_t *cd; ngx_core_conf_t *ccf; ngx_debug_init(); if (ngx_strerror_init() != NGX_OK) { return 1; } if (ngx_get_options(argc, argv) != NGX_OK) { return 1; } if (ngx_show_version) { ngx_show_version_info(); if (!ngx_test_config) { return 0; } } /* TODO */ ngx_max_sockets = -1; ngx_time_init(); #if (NGX_PCRE) ngx_regex_init(); #endif ngx_pid = ngx_getpid(); log = ngx_log_init(ngx_prefix); if (log == NULL) { return 1; } /* STUB */ #if (NGX_OPENSSL) ngx_ssl_init(log); #endif /* * init_cycle->log is required for signal handlers and * ngx_process_options() */ ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); init_cycle.log = log; ngx_cycle = &init_cycle; init_cycle.pool = ngx_create_pool(1024, log); if (init_cycle.pool == NULL) { return 1; } if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } if (ngx_os_init(log) != NGX_OK) { return 1; } /* * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() */ if (ngx_crc32_table_init() != NGX_OK) { return 1; } if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; } cycle = ngx_init_cycle(&init_cycle); if (cycle == NULL) { if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data); } return 1; } if (ngx_test_config) { if (!ngx_quiet_mode) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); } if (ngx_dump_config) { cd = cycle->config_dump.elts; for (i = 0; i < cycle->config_dump.nelts; i++) { ngx_write_stdout("# configuration file "); (void) ngx_write_fd(ngx_stdout, cd[i].name.data, cd[i].name.len); ngx_write_stdout(":" NGX_LINEFEED); b = cd[i].buffer; (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos); ngx_write_stdout(NGX_LINEFEED); } } return 0; } if (ngx_signal) { return ngx_signal_process(cycle, ngx_signal); } ngx_os_status(cycle->log); ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER; } #if !(NGX_WIN32) if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; } if (!ngx_inherited && ccf->daemon) { if (ngx_daemon(cycle->log) != NGX_OK) { return 1; } ngx_daemonized = 1; } if (ngx_inherited) { ngx_daemonized = 1; } #endif if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } if (ngx_log_redirect_stderr(cycle) != NGX_OK) { return 1; } if (log->file->fd != ngx_stderr) { if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed"); } } ngx_use_stderr = 0; if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); } return 0; }
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn) { u_long on; ngx_pid_t pid; ngx_int_t s; if (respawn >= 0) { s = respawn; } else { for (s = 0; s < ngx_last_process; s++) { if (ngx_processes[s].pid == -1) { break; } } if (s == NGX_MAX_PROCESSES) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "no more than %d processes can be spawned", NGX_MAX_PROCESSES); return NGX_INVALID_PID; } } if (respawn != NGX_PROCESS_DETACHED) { /* Solaris 9 still has no AF_LOCAL */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "socketpair() failed while spawning \"%s\"", name); return NGX_INVALID_PID; } ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, "channel %d:%d", ngx_processes[s].channel[0], ngx_processes[s].channel[1]); if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_nonblocking_n " failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_nonblocking_n " failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } on = 1; if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "ioctl(FIOASYNC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(F_SETOWN) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } ngx_channel = ngx_processes[s].channel[1]; } else { ngx_processes[s].channel[0] = -1; ngx_processes[s].channel[1] = -1; } ngx_process_slot = s; pid = fork(); switch (pid) { case -1: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fork() failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; case 0: ngx_pid = ngx_getpid(); proc(cycle, data); break; default: break; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid); ngx_processes[s].pid = pid; ngx_processes[s].exited = 0; if (respawn >= 0) { return pid; } ngx_processes[s].proc = proc; ngx_processes[s].data = data; ngx_processes[s].name = name; ngx_processes[s].exiting = 0; switch (respawn) { case NGX_PROCESS_NORESPAWN: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 0; break; case NGX_PROCESS_JUST_SPAWN: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 1; ngx_processes[s].detached = 0; break; case NGX_PROCESS_RESPAWN: ngx_processes[s].respawn = 1; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 0; break; case NGX_PROCESS_JUST_RESPAWN: ngx_processes[s].respawn = 1; ngx_processes[s].just_spawn = 1; ngx_processes[s].detached = 0; break; case NGX_PROCESS_DETACHED: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 1; break; } if (s == ngx_last_process) { ngx_last_process++; } return pid; }
int query_result_to_cstring(const char* path, char res_string[], size_t size, ngx_http_request_t *r) { int ret = 0; res_string[0] = '\0'; static MYSQL *kconn = NULL; static int kconnected = 0; static int kconnect_times = 0; static int kquery_times = 0; if(!kconnected) { kconnect_times ++; char server[] = "localhost"; char user[] = "root"; char password[] = "[email protected]"; char database[] = "notetask"; kconn = mysql_init(NULL); if (!mysql_real_connect(kconn, server,user, password, database, 0, NULL, 0)) { PRINTF_ERROR("mysql connect error : %s\n", mysql_error(kconn)); mysql_close(kconn); mysql_library_end(); kconn = NULL; kconnected = 0; ret = -1; goto finish; } else { PRINTF_DEBUG("mysql connect OK [%d].\n", getpid()); kconnected = 1; } } //根据请求的path, 组合查询语句. #define LEN_QUERY_STRING (1024) char query_string[LEN_QUERY_STRING]; snprintf(query_string, LEN_QUERY_STRING, "%s", "select * from notetask"); int ret_query = mysql_query(kconn, query_string); kquery_times ++; if(ret_query) { PRINTF_ERROR("mysql query error : %s\n", mysql_error(kconn)); mysql_close(kconn); mysql_library_end(); kconn = NULL; kconnected = 0; ret = -1; goto finish; } MYSQL_ROW sqlrow; MYSQL_RES *res_ptr; size_t len = 0; res_ptr = mysql_store_result(kconn); int64_t uid = 100; int type = 1; int count = 18; int version = 667; int status = 0; const char* title = "当前任务"; int page = 1; int code = 200; int success = 1; const char* message = ""; len += snprintf(res_string, size-len, "{" "\"notetasks\":{" "\"uid\":%"PRIu64"," "\"type\":%d," "\"count\":%d," "\"version\":%d," "\"server\":\"%d.%d.%d.%d\"," "\"status\":%d" "}," "\"page\":{" "\"title\":\"%s\"," "\"page\":%d" "}," "\"code\":%d," "\"success\":%s," "\"message\":\"%s\"," "\"notes\":[", uid, type, count, version, ngx_getpid(), ngx_log_tid, kconnect_times, kquery_times, status, title, page, code, success?"true":"false", message); int row_number = 0; if(res_ptr) { while((sqlrow = mysql_fetch_row(res_ptr)) && len + 1 < size) { row_number ++; len += snprintf(res_string + len, size - len, "%s{" "\"uid\":%s," "\"status\":%s," "\"startDateTime\":\"%s\"," "\"finishDateTime\":\"%s\"," "\"commitDateTime\":\"%s\"," "\"updateDateTime\":\"%s\"," "\"content\":\"%s\"," "\"isShared\":%s," "\"isOnlyLocal\":%s," "\"isOnlyWorkday\":%s," "\"isDailyRepeat\":%s," "\"isWeeklyRepeat\":%s," "\"isYearlyRepeat\":%s," "\"commentNumber\":%ld," "\"likeNumber\":%ld" "}", row_number > 1 ? "," : "", sqlrow[1], sqlrow[2], sqlrow[3], sqlrow[4], sqlrow[5], sqlrow[6], sqlrow[7], sqlrow[8], sqlrow[9], sqlrow[10], sqlrow[11], sqlrow[12], sqlrow[13], atol(sqlrow[14]), atol(sqlrow[15]) ); } if(len+1 < size) { len += snprintf(res_string + len, size - len, "]" "}"); } mysql_free_result(res_ptr); res_ptr = NULL; } else { PRINTF_ERROR("mysql_use_result error : %s.\n", mysql_error(kconn)); mysql_close(kconn); mysql_library_end(); kconn = NULL; kconnected = 0; ret = -1; goto finish; } finish: return ret; }
static char * xml_log_merge_conf(ngx_conf_t *cf, void *parent, void *child) { xml_log_conf_t *prev = parent; xml_log_conf_t *conf = child; ngx_open_file_t *file; ngx_str_t *str; ngx_conf_merge_path_value(conf->path, prev->path, "/",1,2,0,ngx_garbage_collector_temp_handler,cf); if((&conf->path->name)->len > 1) { conf->enable=1; str=ngx_pcalloc(cf->pool,sizeof(ngx_str_t)); str->data=ngx_pcalloc(cf->pool,(&conf->path->name)->len+15); (&conf->path->name)->data[(&conf->path->name)->len]=0; ngx_snprintf(str->data,(&conf->path->name)->len+15,"%s/%d.xml.tmp",(&conf->path->name)->data,ngx_getpid()); if((conf->file=ngx_conf_open_file(cf->cycle,str)) == NULL) return NGX_CONF_ERROR; } return NGX_CONF_OK; }
/* * 创建进程 */ ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn) { u_long on; ngx_pid_t pid; ngx_int_t s; if (respawn >= 0) { s = respawn; } else { /*在全局进程表 ngx_processes 中查找第一个空的结构,用来存放新创建的进程的信息*/ for (s = 0; s < ngx_last_process; s++) { if (ngx_processes[s].pid == -1) { break; } } if (s == NGX_MAX_PROCESSES) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "no more than %d processes can be spawned", NGX_MAX_PROCESSES); return NGX_INVALID_PID; } } if (respawn != NGX_PROCESS_DETACHED) { /* Solaris 9 still has no AF_LOCAL */ /*调用 socketpair 创建一对互相连接的 unix域socket,用于进程间的全双工通信*/ if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "socketpair() failed while spawning \"%s\"", name); return NGX_INVALID_PID; } ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, "channel %d:%d", ngx_processes[s].channel[0], ngx_processes[s].channel[1]); /*将用于进程通信的 socket 设置成非阻塞的*/ if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_nonblocking_n " failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_nonblocking_n " failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } on = 1; /*设置成信号驱动异步IO,有IO时内核发送SIGIO信号*/ if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "ioctl(FIOASYNC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } /*设置将接受 SIGIO 和 SIGURG 信号的进程id*/ if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(F_SETOWN) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } /*当执行 exec 时关闭描述符*/ if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } /*当前子进程的描述符*/ ngx_channel = ngx_processes[s].channel[1]; } else { ngx_processes[s].channel[0] = -1; ngx_processes[s].channel[1] = -1; } /*新创建进的进程在 ngx_processes 数组中的下标*/ ngx_process_slot = s; pid = fork(); switch (pid) { case -1: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fork() failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; case 0: //子进程 ngx_pid = ngx_getpid(); proc(cycle, data); break; default: break; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid); /*新创建的进程放入 master 主进程的 ngx_processes 数组中*/ ngx_processes[s].pid = pid; ngx_processes[s].exited = 0; if (respawn >= 0) { return pid; } ngx_processes[s].proc = proc; ngx_processes[s].data = data; ngx_processes[s].name = name; ngx_processes[s].exiting = 0; switch (respawn) { case NGX_PROCESS_NORESPAWN: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 0; break; case NGX_PROCESS_JUST_SPAWN: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 1; ngx_processes[s].detached = 0; break; case NGX_PROCESS_RESPAWN: ngx_processes[s].respawn = 1; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 0; break; case NGX_PROCESS_JUST_RESPAWN: ngx_processes[s].respawn = 1; ngx_processes[s].just_spawn = 1; ngx_processes[s].detached = 0; break; case NGX_PROCESS_DETACHED: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 1; break; } if (s == ngx_last_process) { ngx_last_process++; } return pid; }
int ngx_cdecl main(int argc, char *const *argv) { ngx_int_t i; ngx_log_t *log; ngx_cycle_t *cycle, init_cycle; ngx_core_conf_t *ccf; ngx_debug_init(); if (ngx_strerror_init() != NGX_OK) { //初始化错误编号的错误字符串数组 return 1; } if (ngx_get_options(argc, argv) != NGX_OK) { //命令行处理 return 1; } //如果ngx_show_version由上面的ngx_get_options置为1 if (ngx_show_version) { ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED); //显示宏定义 if (ngx_show_help) { ngx_write_stderr( "Usage: nginx [-?hvVtq] [-s signal] [-c filename] " "[-p prefix] [-g directives]" NGX_LINEFEED NGX_LINEFEED "Options:" NGX_LINEFEED " -?,-h : this help" NGX_LINEFEED " -v : show version and exit" NGX_LINEFEED " -V : show version and configure options then exit" NGX_LINEFEED " -t : test configuration and exit" NGX_LINEFEED " -q : suppress non-error messages " "during configuration testing" NGX_LINEFEED " -s signal : send signal to a master process: " "stop, quit, reopen, reload" NGX_LINEFEED #ifdef NGX_PREFIX " -p prefix : set prefix path (default: " NGX_PREFIX ")" NGX_LINEFEED #else " -p prefix : set prefix path (default: NONE)" NGX_LINEFEED #endif " -c filename : set configuration file (default: " NGX_CONF_PATH ")" NGX_LINEFEED " -g directives : set global directives out of configuration " "file" NGX_LINEFEED NGX_LINEFEED ); } if (ngx_show_configure) { #ifdef NGX_COMPILER ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED); #endif #if (NGX_SSL) if (SSLeay() == SSLEAY_VERSION_NUMBER) { ngx_write_stderr("built with " OPENSSL_VERSION_TEXT NGX_LINEFEED); } else { ngx_write_stderr("built with " OPENSSL_VERSION_TEXT " (running with "); ngx_write_stderr((char *) (uintptr_t) SSLeay_version(SSLEAY_VERSION)); ngx_write_stderr(")" NGX_LINEFEED); } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED); #else ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED); #endif #endif ngx_write_stderr("configure arguments:" NGX_CONFIGURE NGX_LINEFEED); } if (!ngx_test_config) { return 0; } } /* TODO */ ngx_max_sockets = -1; ngx_time_init(); //时间初始化 #if (NGX_PCRE) ngx_regex_init(); #endif ngx_pid = ngx_getpid(); //获得主进程pid log = ngx_log_init(ngx_prefix); //初始化log if (log == NULL) { return 1; } /* STUB */ #if (NGX_OPENSSL) ngx_ssl_init(log); #endif /* * init_cycle->log is required for signal handlers and * ngx_process_options() */ //构造一个init_cycle,旧的预处理 ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); init_cycle.log = log; ngx_cycle = &init_cycle; //init_cycle是在栈中的 init_cycle.pool = ngx_create_pool(1024, log); //1K大小内存 if (init_cycle.pool == NULL) { return 1; } //拷贝一份argv if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } //处理命令行选项 if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } if (ngx_os_init(log) != NGX_OK) { return 1; } /* * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() */ if (ngx_crc32_table_init() != NGX_OK) { return 1; } //从环境变量中继承一些监听描述符,用于平滑升级 if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } //设置模块的编号,从0开始计数 ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; } cycle = ngx_init_cycle(&init_cycle); //创建新的cycle if (cycle == NULL) { if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data); } return 1; } if (ngx_test_config) { if (!ngx_quiet_mode) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); } return 0; } if (ngx_signal) { //如果要向指定的进程发送信号 return ngx_signal_process(cycle, ngx_signal); } ngx_os_status(cycle->log); ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER; //以多进程方式工作 } #if !(NGX_WIN32) if (ngx_init_signals(cycle->log) != NGX_OK) { //初始化信号相关操作 return 1; } if (!ngx_inherited && ccf->daemon) { if (ngx_daemon(cycle->log) != NGX_OK) { //以守护进程来运行 return 1; } ngx_daemonized = 1; } if (ngx_inherited) { ngx_daemonized = 1; } #endif //创建进程的pid的文件 if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } if (ngx_log_redirect_stderr(cycle) != NGX_OK) { return 1; } if (log->file->fd != ngx_stderr) { if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed"); } } ngx_use_stderr = 0; if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); //以多进程方式运行 } return 0; }
//1.时间、正则、错误日志、ssl等初始化 //2.读入命令行参数 //3.OS相关初始化 //4.读入并解析配置 //5.核心模块初始化 //6.创建各种临时文件和目录 //7.创建共享内存 //8.打开listen的端口 //9.所有模块初始化 //10.启动worker进程 int ngx_cdecl main(int argc, char *const *argv) { ngx_int_t i; ngx_log_t *log; ngx_cycle_t *cycle, init_cycle; ngx_core_conf_t *ccf; #if (NGX_FREEBSD) ngx_debug_init(); #endif if (ngx_strerror_init() != NGX_OK) { return 1; } //获取参数和配置参数,比如命令是nginx -v 那么ngx_show_version就设置为1 if (ngx_get_options(argc, argv) != NGX_OK) { return 1; } if (ngx_show_version) { ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED); if (ngx_show_help) { ngx_write_stderr( "Usage: nginx [-?hvVtq] [-s signal] [-c filename] " "[-p prefix] [-g directives]" NGX_LINEFEED NGX_LINEFEED "Options:" NGX_LINEFEED " -?,-h : this help" NGX_LINEFEED " -v : show version and exit" NGX_LINEFEED " -V : show version and configure options then exit" NGX_LINEFEED " -t : test configuration and exit" NGX_LINEFEED " -q : suppress non-error messages " "during configuration testing" NGX_LINEFEED " -s signal : send signal to a master process: " "stop, quit, reopen, reload" NGX_LINEFEED #ifdef NGX_PREFIX " -p prefix : set prefix path (default: " NGX_PREFIX ")" NGX_LINEFEED #else " -p prefix : set prefix path (default: NONE)" NGX_LINEFEED #endif " -c filename : set configuration file (default: " NGX_CONF_PATH ")" NGX_LINEFEED " -g directives : set global directives out of configuration " "file" NGX_LINEFEED NGX_LINEFEED ); } if (ngx_show_configure) { ngx_write_stderr( #ifdef NGX_COMPILER "built by " NGX_COMPILER NGX_LINEFEED #endif #if (NGX_SSL) #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME "TLS SNI support enabled" NGX_LINEFEED #else "TLS SNI support disabled" NGX_LINEFEED #endif #endif "configure arguments:" NGX_CONFIGURE NGX_LINEFEED); } if (!ngx_test_config) { return 0; } } /* TODO */ ngx_max_sockets = -1; //初始化nginx环境的当前时间 ngx_time_init(); #if (NGX_PCRE) ngx_regex_init(); #endif //master pid, 获取当前进程ID ngx_pid = ngx_getpid(); // 初始化日志,如打开日志文件 log = ngx_log_init(ngx_prefix); if (log == NULL) { return 1; } /* STUB */ #if (NGX_OPENSSL) ngx_ssl_init(log); //是否开启了ssl,如果开启在这里进行初始化 #endif /* * init_cycle->log is required for signal handlers and * ngx_process_options() */ ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); init_cycle.log = log; ngx_cycle = &init_cycle; // 为cycle创建一个1024B的内存池 init_cycle.pool = ngx_create_pool(1024, log); if (init_cycle.pool == NULL) { return 1; } // 保存参数到全局变量中 if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } // 初始化init_cycle中的一些如: conf_file,prefix,conf_prefix等字段 if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } // 初始化系统相关变量,如内存页面大小ngx_pagesize,ngx_cacheline_size,最大连接数ngx_max_sockets等 if (ngx_os_init(log) != NGX_OK) { // 这个ngx_os_init在不同操作系统调用不同的函数 return 1; } /* * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() */ // 初始化CRC表,提高效率,以后就不用计算了,直接用 if (ngx_crc32_table_init() != NGX_OK) { return 1; } // 继承sockets,继承来的socket将会放到init_cycle的listening数组 if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } // 计算模块个数,并且设置各个模块顺序(索引) ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { // 这里面的ngx_modules会有非常多的模块,[ngx_core_module,ngx_errlog_module,ngx_conf_moduel] ngx_modules[i]->index = ngx_max_module++; } // 对ngx_cycle结构进行初始化,这里是nginx启动核心之处! cycle = ngx_init_cycle(&init_cycle); if (cycle == NULL) { if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data); } return 1; } if (ngx_test_config) { if (!ngx_quiet_mode) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); } return 0; } // 检查是否有设置信号处理,如有,进入ngx_signal_process处理 if (ngx_signal) { return ngx_signal_process(cycle, ngx_signal); } ngx_os_status(cycle->log); ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER; } #if !(NGX_WIN32) if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; } if (!ngx_inherited && ccf->daemon) { if (ngx_daemon(cycle->log) != NGX_OK) { //如果是daemon模式,本进程变为守护进程 return 1; } ngx_daemonized = 1; } if (ngx_inherited) { ngx_daemonized = 1; } #endif // 创建进程记录文件 if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } if (cycle->log->file->fd != ngx_stderr) { if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_set_stderr_n " failed"); return 1; } } if (log->file->fd != ngx_stderr) { if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed"); } } ngx_use_stderr = 0; if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); //单进程 } else { ngx_master_process_cycle(cycle); //多进程,master进程进入这个,这个函数在不同操作系统有不同实现。 } return 0; }
//创建子进程 ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn) { u_long on; ngx_pid_t pid; ngx_int_t s; if (respawn >= 0) { s = respawn; } else { //初始化ngx_processes数组 for (s = 0; s < ngx_last_process; s++) { if (ngx_processes[s].pid == -1) { break; } } //进程个数不能大于NGX_MAX_PROCESSES if (s == NGX_MAX_PROCESSES) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "no more than %d processes can be spawned", NGX_MAX_PROCESSES); return NGX_INVALID_PID; } } if (respawn != NGX_PROCESS_DETACHED) { /* Solaris 9 still has no AF_LOCAL */ //创建用于进程间通信的UNIX域套结字 if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "socketpair() failed while spawning \"%s\"", name); return NGX_INVALID_PID; } ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, "channel %d:%d", ngx_processes[s].channel[0], ngx_processes[s].channel[1]); //将套结字的读写端都设置为非阻塞 if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_nonblocking_n " failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_nonblocking_n " failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } on = 1; //以下设置套结字读端为信号驱动,注意我们还没有fork子进程,设置是在master进程中 //设置FIOASYNC标志(我们必须要这样做),fcntl函数也可以设置,但大多数系统不支持, //因此用ioctl来实现 if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "ioctl(FIOASYNC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //设置F_SETOWN标志,将套结字读端和master进程关联起来,当管道有数据的时侯会向该进程 //发送SIGIO信号 if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(F_SETOWN) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //设置管道的FD_CLOEXEC标志 if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } ngx_channel = ngx_processes[s].channel[1]; } else { ngx_processes[s].channel[0] = -1; ngx_processes[s].channel[1] = -1; } ngx_process_slot = s; pid = fork(); switch (pid) { case -1: //error ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fork() failed while spawning \"%s\"", name); ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; case 0: //child ngx_pid = ngx_getpid(); //执行我们传递的子进程执行函数 proc(cycle, data); break; default: //father break; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid); ngx_processes[s].pid = pid; ngx_processes[s].exited = 0; if (respawn >= 0) { return pid; } ngx_processes[s].proc = proc; //设置子进程的执行函数 ngx_processes[s].data = data; //设置子进程的参数 ngx_processes[s].name = name; //设置子进程的name ngx_processes[s].exiting = 0; switch (respawn) { case NGX_PROCESS_NORESPAWN: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 0; break; case NGX_PROCESS_JUST_SPAWN: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 1; ngx_processes[s].detached = 0; break; case NGX_PROCESS_RESPAWN: ngx_processes[s].respawn = 1; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 0; break; case NGX_PROCESS_JUST_RESPAWN: ngx_processes[s].respawn = 1; ngx_processes[s].just_spawn = 1; ngx_processes[s].detached = 0; break; case NGX_PROCESS_DETACHED: ngx_processes[s].respawn = 0; ngx_processes[s].just_spawn = 0; ngx_processes[s].detached = 1; break; } if (s == ngx_last_process) { ngx_last_process++; //last_proces可以视为子进程个数 } return pid; }