step 1
ngx_debug_init(); //linux下為空函數
step 2
if (ngx_strerror_init() != NGX_OK) {
return 1; }
NGX_SYS_NERR,定義在/home/nginx-1.4.4/objs/ngx_auto_config.h, configure的時候自動生成,生成的辦法待研究
debian下的大小為:
static ngx_str_t *ngx_sys_errlist;//指向一個NGX_SYS_NERR * sizeof(ngx_str_t);大小的記憶體
//周遊NGX_SYS_NERR這麼多個err for (err = 0; err < NGX_SYS_NERR; err++) {
msg = strerror(err); //strerror()用來翻譯錯誤碼的宏定義的意思
len = ngx_strlen(msg);
p = malloc(len);
if (p == NULL) {
goto failed;
}
ngx_memcpy(p, msg, len); //開一塊記憶體,将錯誤碼對應的意思拷貝進去 //将以錯誤碼為下标的元素指派,之後通過錯誤碼可以直接和錯誤意思對應
ngx_sys_errlist[err].len = len;
ngx_sys_errlist[err].data = p;
}
step 3
if (ngx_get_options(argc, argv) != NGX_OK) {
return 1;
}
初始化各環境變量(全局變量)
step 4
ngx_time_init();
伺服器時間的初始化,不明覺厲,需要看到後面再回來研究。
step 5
#if (NGX_PCRE)
ngx_regex_init();
#endif
正則初始化, 不明覺厲,需要看到後面再回來研究。
step 6
ngx_pid = ngx_getpid();
取得目前程序的程序pid
step 7
log = ngx_log_init(ngx_prefix);
if (log == NULL) {
return 1;
}
日志初始化,日志子產品後面會單獨開辟一章來分析,先留白。
step 8
#if (NGX_OPENSSL)
ngx_ssl_init(log);
#endif
SSL初始化
step 9
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_cycle_t的局部變量,初始化該結構的log指針,pool指針
step 10
if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
return 1;
}
把main函數的argc, argv存在ngx_os_argv、ngx_argc、ngx_argv這三個全局變量裡面, 不明覺厲,日後再說。
step 11
if (ngx_process_options(&init_cycle) != NGX_OK) {
return 1;
}
初始化 ngx_cycle結構體 的 prefix, conf_prefix, conf_file, conf_param 等字段
初始化這些結構體變量是根據ngx_prefix、ngx_conf_file、ngx_conf_params等全局變量來的,而這些全局變量是在ngx_get_options()函數中進行的初始化。
- static u_char *ngx_prefix;
- static u_char *ngx_conf_file;
- static u_char *ngx_conf_params;
step 12
if (ngx_os_init(log) != NGX_OK) {
return 1;
}
初始化系統相關變量,如記憶體頁面大小 ngx_pagesize , ngx_cacheline_size , 最大連接配接數 ngx_max_sockets 等;
ngx_int_t
ngx_os_init(ngx_log_t *log)
{
ngx_uint_t n;
#if (NGX_HAVE_OS_SPECIFIC_INIT)
if (ngx_os_specific_init(log) != NGX_OK) {
return NGX_ERROR;
}
#endif
ngx_init_setproctitle(log);
//傳回一分頁的大小, 機關為位元組(byte). 此為系統的分頁大小, 不一定會和硬體分頁大小相同.
//在intel x86上為4096 bytes
ngx_pagesize = getpagesize();
//設定cpu cacheline大小,該宏定義在./ngx_auto_config.h:#define NGX_CPU_CACHE_LINE 32
//http://blog.csdn.net/zdl1016/article/details/8882092
ngx_cacheline_size = NGX_CPU_CACHE_LINE;
//每次循環,n折半
for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }
#if (NGX_HAVE_SC_NPROCESSORS_ONLN)
if (ngx_ncpu == 0) {
ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN);
}
#endif
if (ngx_ncpu < 1) {
ngx_ncpu = 1;
}
//不明覺厲,根據CPU類型設定ngx_cacheline_size的大小
ngx_cpuinfo();
//RLIMIT_NOFILE參數,擷取程序可以打開的最多檔案數,APUE II P164.之7.11節
if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"getrlimit(RLIMIT_NOFILE) failed)");
return NGX_ERROR;
}
//記錄能打開的最大檔案數到ngx_max_sockets全局變量
ngx_max_sockets = (ngx_int_t) rlmt.rlim_cur;
#if (NGX_HAVE_INHERITED_NONBLOCK || NGX_HAVE_ACCEPT4)
ngx_inherited_nonblocking = 1;
#else
ngx_inherited_nonblocking = 0;
#endif
//設定random函數的種子
srandom(ngx_time());
return NGX_OK;
}
btw: 關于系統軟限制和硬限制的檢視方式如下
step 13
if (ngx_crc32_table_init() != NGX_OK) {
return 1;
}
不明覺厲,需要專門分析。
step 14
if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
return 1;
}
不明覺厲,需要專門分析。
step 15
ngx_max_module = 0;
for (i = 0; ngx_modules[i]; i++) {
ngx_modules[i]->index = ngx_max_module++;
}
初始化每個 module 的 index ,并計算module的最大值 ngx_max_module
step 16
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;
}
對 ngx_cycle 結構進行初始化, 重要,需要細看。
step 17
if (ngx_signal) {
return ngx_signal_process(cycle, ngx_signal);
}
若有信号,則處理信号。
step 18
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;
}
step 19
if (ngx_init_signals(cycle->log) != NGX_OK) {
return 1;
}
該函數根據signals來初始化信号。
signals[ ]的定義在src/os/unix/ngx_process.c中,定義了各種信号的處理函數。
step 20
if (!ngx_inherited && ccf->daemon) {
if (ngx_daemon(cycle->log) != NGX_OK) {
return 1;
}
ngx_daemonized = 1;
}
if (ngx_inherited) {
ngx_daemonized = 1;
}
沒看懂,待分析
step 21
if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
return 1;
}
建立程序記錄檔案
step 22
if (ngx_process == NGX_PROCESS_SINGLE) {
ngx_single_process_cycle(cycle);
} else {
ngx_master_process_cycle(cycle);
}
進入程序主循環;
- 若為NGX_PROCESS_SINGLE=1模式,則調用ngx_single_process_cycle()進入程序循環;
- 否則為master-worker模式,調用ngx_master_process_cycle()進入程序循環;