Nginx的启动过程
主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程。
涉及到的基本函数
源码:
1 /* 2 * Copyright (C) Igor Sysoev 3 * Copyright (C) Nginx, Inc. 4 */ 5 6 7 #include <ngx_config.h> 8 #include <ngx_core.h> 9 #include <nginx.h> 10 11 12 static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle); 13 static ngx_int_t ngx_get_options(int argc, char *const *argv); 14 static ngx_int_t ngx_process_options(ngx_cycle_t *cycle); 15 static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv); 16 static void *ngx_core_module_create_conf(ngx_cycle_t *cycle); 17 static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf); 18 static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 19 static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 20 static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 21 static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, 22 void *conf); 23 static char *ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, 24 void *conf); 25 26 27 static ngx_conf_enum_t ngx_debug_points[] = { 28 { ngx_string("stop"), NGX_DEBUG_POINTS_STOP }, 29 { ngx_string("abort"), NGX_DEBUG_POINTS_ABORT }, 30 { ngx_null_string, 0 } 31 }; 32 33 34 static ngx_command_t ngx_core_commands[] = { 35 36 { ngx_string("daemon"), 37 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, 38 ngx_conf_set_flag_slot, 39 0, 40 offsetof(ngx_core_conf_t, daemon), 41 NULL }, 42 43 { ngx_string("master_process"), 44 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, 45 ngx_conf_set_flag_slot, 46 0, 47 offsetof(ngx_core_conf_t, master), 48 NULL }, 49 50 { ngx_string("timer_resolution"), 51 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 52 ngx_conf_set_msec_slot, 53 0, 54 offsetof(ngx_core_conf_t, timer_resolution), 55 NULL }, 56 57 { ngx_string("pid"), 58 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 59 ngx_conf_set_str_slot, 60 0, 61 offsetof(ngx_core_conf_t, pid), 62 NULL }, 63 64 { ngx_string("lock_file"), 65 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 66 ngx_conf_set_str_slot, 67 0, 68 offsetof(ngx_core_conf_t, lock_file), 69 NULL }, 70 71 { ngx_string("worker_processes"), 72 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 73 ngx_set_worker_processes, 74 0, 75 0, 76 NULL }, 77 78 { ngx_string("debug_points"), 79 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 80 ngx_conf_set_enum_slot, 81 0, 82 offsetof(ngx_core_conf_t, debug_points), 83 &ngx_debug_points }, 84 85 { ngx_string("user"), 86 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12, 87 ngx_set_user, 88 0, 89 0, 90 NULL }, 91 92 { ngx_string("worker_priority"), 93 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 94 ngx_set_priority, 95 0, 96 0, 97 NULL }, 98 99 { ngx_string("worker_cpu_affinity"), 100 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE, 101 ngx_set_cpu_affinity, 102 0, 103 0, 104 NULL }, 105 106 { ngx_string("worker_rlimit_nofile"), 107 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 108 ngx_conf_set_num_slot, 109 0, 110 offsetof(ngx_core_conf_t, rlimit_nofile), 111 NULL }, 112 113 { ngx_string("worker_rlimit_core"), 114 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 115 ngx_conf_set_off_slot, 116 0, 117 offsetof(ngx_core_conf_t, rlimit_core), 118 NULL }, 119 120 { ngx_string("worker_rlimit_sigpending"), 121 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 122 ngx_conf_set_num_slot, 123 0, 124 offsetof(ngx_core_conf_t, rlimit_sigpending), 125 NULL }, 126 127 { ngx_string("working_directory"), 128 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 129 ngx_conf_set_str_slot, 130 0, 131 offsetof(ngx_core_conf_t, working_directory), 132 NULL }, 133 134 { ngx_string("env"), 135 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 136 ngx_set_env, 137 0, 138 0, 139 NULL }, 140 141 #if (NGX_THREADS) 142 143 { ngx_string("worker_threads"), 144 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 145 ngx_conf_set_num_slot, 146 0, 147 offsetof(ngx_core_conf_t, worker_threads), 148 NULL }, 149 150 { ngx_string("thread_stack_size"), 151 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 152 ngx_conf_set_size_slot, 153 0, 154 offsetof(ngx_core_conf_t, thread_stack_size), 155 NULL }, 156 157 #endif 158 159 ngx_null_command 160 }; 161 162 163 static ngx_core_module_t ngx_core_module_ctx = { 164 ngx_string("core"), 165 ngx_core_module_create_conf, 166 ngx_core_module_init_conf 167 }; 168 169 170 ngx_module_t ngx_core_module = { 171 NGX_MODULE_V1, 172 &ngx_core_module_ctx, /* module context */ 173 ngx_core_commands, /* module directives */ 174 NGX_CORE_MODULE, /* module type */ 175 NULL, /* init master */ 176 NULL, /* init module */ 177 NULL, /* init process */ 178 NULL, /* init thread */ 179 NULL, /* exit thread */ 180 NULL, /* exit process */ 181 NULL, /* exit master */ 182 NGX_MODULE_V1_PADDING 183 }; 184 185 186 ngx_uint_t ngx_max_module; 187 188 static ngx_uint_t ngx_show_help; 189 static ngx_uint_t ngx_show_version; 190 static ngx_uint_t ngx_show_configure; 191 static u_char *ngx_prefix; 192 static u_char *ngx_conf_file; 193 static u_char *ngx_conf_params; 194 static char *ngx_signal; 195 196 197 static char **ngx_os_environ; 198 199 200 int ngx_cdecl 201 main(int argc, char *const *argv) 202 { 203 ngx_int_t i; 204 ngx_log_t *log; 205 ngx_cycle_t *cycle, init_cycle; 206 ngx_core_conf_t *ccf; 207 208 ngx_debug_init(); 209 210 if (ngx_strerror_init() != NGX_OK) { 211 return 1; 212 } 213 214 if (ngx_get_options(argc, argv) != NGX_OK) { 215 return 1; 216 } 217 218 if (ngx_show_version) { 219 ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED); 220 221 if (ngx_show_help) { 222 ngx_write_stderr( 223 "Usage: nginx [-?hvVtq] [-s signal] [-c filename] " 224 "[-p prefix] [-g directives]" NGX_LINEFEED 225 NGX_LINEFEED 226 "Options:" NGX_LINEFEED 227 " -?,-h : this help" NGX_LINEFEED 228 " -v : show version and exit" NGX_LINEFEED 229 " -V : show version and configure options then exit" 230 NGX_LINEFEED 231 " -t : test configuration and exit" NGX_LINEFEED 232 " -q : suppress non-error messages " 233 "during configuration testing" NGX_LINEFEED 234 " -s signal : send signal to a master process: " 235 "stop, quit, reopen, reload" NGX_LINEFEED 236 #ifdef NGX_PREFIX 237 " -p prefix : set prefix path (default: " 238 NGX_PREFIX ")" NGX_LINEFEED 239 #else 240 " -p prefix : set prefix path (default: NONE)" NGX_LINEFEED 241 #endif 242 " -c filename : set configuration file (default: " 243 NGX_CONF_PATH ")" NGX_LINEFEED 244 " -g directives : set global directives out of configuration " 245 "file" NGX_LINEFEED NGX_LINEFEED 246 ); 247 } 248 249 if (ngx_show_configure) { 250 ngx_write_stderr( 251 #ifdef NGX_COMPILER 252 "built by " NGX_COMPILER NGX_LINEFEED 253 #endif 254 #if (NGX_SSL) 255 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME 256 "TLS SNI support enabled" NGX_LINEFEED 257 #else 258 "TLS SNI support disabled" NGX_LINEFEED 259 #endif 260 #endif 261 "configure arguments:" NGX_CONFIGURE NGX_LINEFEED); 262 } 263 264 if (!ngx_test_config) { 265 return 0; 266 } 267 } 268 269 /* TODO */ ngx_max_sockets = -1; 270 271 ngx_time_init(); 272 273 #if (NGX_PCRE) 274 ngx_regex_init(); 275 #endif 276 277 ngx_pid = ngx_getpid(); 278 279 log = ngx_log_init(ngx_prefix); 280 if (log == NULL) { 281 return 1; 282 } 283 284 /* STUB */ 285 #if (NGX_OPENSSL) 286 ngx_ssl_init(log); 287 #endif 288 289 /* 290 * init_cycle->log is required for signal handlers and 291 * ngx_process_options() 292 */ 293 294 ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); 295 init_cycle.log = log; 296 ngx_cycle = &init_cycle; 297 298 init_cycle.pool = ngx_create_pool(1024, log); 299 if (init_cycle.pool == NULL) { 300 return 1; 301 } 302 303 if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { 304 return 1; 305 } 306 307 if (ngx_process_options(&init_cycle) != NGX_OK) { 308 return 1; 309 } 310 311 if (ngx_os_init(log) != NGX_OK) { 312 return 1; 313 } 314 315 /* 316 * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() 317 */ 318 319 if (ngx_crc32_table_init() != NGX_OK) { 320 return 1; 321 } 322 323 if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { 324 return 1; 325 } 326 327 ngx_max_module = 0; 328 for (i = 0; ngx_modules[i]; i++) { 329 ngx_modules[i]->index = ngx_max_module++; 330 } 331 332 cycle = ngx_init_cycle(&init_cycle); 333 if (cycle == NULL) { 334 if (ngx_test_config) { 335 ngx_log_stderr(0, "configuration file %s test failed", 336 init_cycle.conf_file.data); 337 } 338 339 return 1; 340 } 341 342 if (ngx_test_config) { 343 if (!ngx_quiet_mode) { 344 ngx_log_stderr(0, "configuration file %s test is successful", 345 cycle->conf_file.data); 346 } 347 348 return 0; 349 } 350 351 if (ngx_signal) { 352 return ngx_signal_process(cycle, ngx_signal); 353 } 354 355 ngx_os_status(cycle->log); 356 357 ngx_cycle = cycle; 358 359 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); 360 361 if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { 362 ngx_process = NGX_PROCESS_MASTER; 363 } 364 365 #if !(NGX_WIN32) 366 367 if (ngx_init_signals(cycle->log) != NGX_OK) { 368 return 1; 369 } 370 371 if (!ngx_inherited && ccf->daemon) { 372 if (ngx_daemon(cycle->log) != NGX_OK) { 373 return 1; 374 } 375 376 ngx_daemonized = 1; 377 } 378 379 if (ngx_inherited) { 380 ngx_daemonized = 1; 381 } 382 383 #endif 384 385 if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { 386 return 1; 387 } 388 389 if (cycle->log->file->fd != ngx_stderr) { 390 391 if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) { 392 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, 393 ngx_set_stderr_n " failed"); 394 return 1; 395 } 396 } 397 398 if (log->file->fd != ngx_stderr) { 399 if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { 400 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, 401 ngx_close_file_n " built-in log failed"); 402 } 403 } 404 405 ngx_use_stderr = 0; 406 407 if (ngx_process == NGX_PROCESS_SINGLE) { 408 ngx_single_process_cycle(cycle); 409 410 } else { 411 ngx_master_process_cycle(cycle); 412 } 413 414 return 0; 415 } 416 417 418 static ngx_int_t 419 ngx_add_inherited_sockets(ngx_cycle_t *cycle) 420 { 421 u_char *p, *v, *inherited; 422 ngx_int_t s; 423 ngx_listening_t *ls; 424 425 inherited = (u_char *) getenv(NGINX_VAR); 426 427 if (inherited == NULL) { 428 return NGX_OK; 429 } 430 431 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, 432 "using inherited sockets from "%s"", inherited); 433 434 if (ngx_array_init(&cycle->listening, cycle->pool, 10, 435 sizeof(ngx_listening_t)) 436 != NGX_OK) 437 { 438 return NGX_ERROR; 439 } 440 441 for (p = inherited, v = p; *p; p++) { 442 if (*p == ':' || *p == ';') { 443 s = ngx_atoi(v, p - v); 444 if (s == NGX_ERROR) { 445 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, 446 "invalid socket number "%s" in " NGINX_VAR 447 " environment variable, ignoring the rest" 448 " of the variable", v); 449 break; 450 } 451 452 v = p + 1; 453 454 ls = ngx_array_push(&cycle->listening); 455 if (ls == NULL) { 456 return NGX_ERROR; 457 } 458 459 ngx_memzero(ls, sizeof(ngx_listening_t)); 460 461 ls->fd = (ngx_socket_t) s; 462 } 463 } 464 465 ngx_inherited = 1; 466 467 return ngx_set_inherited_sockets(cycle); 468 } 469 470 471 char ** 472 ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last) 473 { 474 char **p, **env; 475 ngx_str_t *var; 476 ngx_uint_t i, n; 477 ngx_core_conf_t *ccf; 478 479 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); 480 481 if (last == NULL && ccf->environment) { 482 return ccf->environment; 483 } 484 485 var = ccf->env.elts; 486 487 for (i = 0; i < ccf->env.nelts; i++) { 488 if (ngx_strcmp(var[i].data, "TZ") == 0 489 || ngx_strncmp(var[i].data, "TZ=", 3) == 0) 490 { 491 goto tz_found; 492 } 493 } 494 495 var = ngx_array_push(&ccf->env); 496 if (var == NULL) { 497 return NULL; 498 } 499 500 var->len = 2; 501 var->data = (u_char *) "TZ"; 502 503 var = ccf->env.elts; 504 505 tz_found: 506 507 n = 0; 508 509 for (i = 0; i < ccf->env.nelts; i++) { 510 511 if (var[i].data[var[i].len] == '=') { 512 n++; 513 continue; 514 } 515 516 for (p = ngx_os_environ; *p; p++) { 517 518 if (ngx_strncmp(*p, var[i].data, var[i].len) == 0 519 && (*p)[var[i].len] == '=') 520 { 521 n++; 522 break; 523 } 524 } 525 } 526 527 if (last) { 528 env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log); 529 *last = n; 530 531 } else { 532 env = ngx_palloc(cycle->pool, (n + 1) * sizeof(char *)); 533 } 534 535 if (env == NULL) { 536 return NULL; 537 } 538 539 n = 0; 540 541 for (i = 0; i < ccf->env.nelts; i++) { 542 543 if (var[i].data[var[i].len] == '=') { 544 env[n++] = (char *) var[i].data; 545 continue; 546 } 547 548 for (p = ngx_os_environ; *p; p++) { 549 550 if (ngx_strncmp(*p, var[i].data, var[i].len) == 0 551 && (*p)[var[i].len] == '=') 552 { 553 env[n++] = *p; 554 break; 555 } 556 } 557 } 558 559 env[n] = NULL; 560 561 if (last == NULL) { 562 ccf->environment = env; 563 environ = env; 564 } 565 566 return env; 567 } 568 569 570 ngx_pid_t 571 ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv) 572 { 573 char **env, *var; 574 u_char *p; 575 ngx_uint_t i, n; 576 ngx_pid_t pid; 577 ngx_exec_ctx_t ctx; 578 ngx_core_conf_t *ccf; 579 ngx_listening_t *ls; 580 581 ngx_memzero(&ctx, sizeof(ngx_exec_ctx_t)); 582 583 ctx.path = argv[0]; 584 ctx.name = "new binary process"; 585 ctx.argv = argv; 586 587 n = 2; 588 env = ngx_set_environment(cycle, &n); 589 if (env == NULL) { 590 return NGX_INVALID_PID; 591 } 592 593 var = ngx_alloc(sizeof(NGINX_VAR) 594 + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2, 595 cycle->log); 596 if (var == NULL) { 597 ngx_free(env); 598 return NGX_INVALID_PID; 599 } 600 601 p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR)); 602 603 ls = cycle->listening.elts; 604 for (i = 0; i < cycle->listening.nelts; i++) { 605 p = ngx_sprintf(p, "%ud;", ls[i].fd); 606 } 607 608 *p = '