. 序
1. main()分析
2. 注意問題
2.1 幾個初值
2.2 nginx工作模式
2.3 一些配置
2.4 其他開關
3. 小結
0. 序
本文主要分析nginx主程序。
nginx主程序main()實現文件:./src/core/nginx.c。.表示nginx-1.0.4代碼目錄,本文為/usr/src/nginx-1.0.4。
1. main()分析
nginx啟動過程如下。
- 調用ngx_get_options()解析命令參數;
- 調用ngx_time_init()初始化并更新時間,如全局變量ngx_cached_time;
- 調用ngx_log_init()初始化日志,如初始化全局變量ngx_prefix,打開日志文件ngx_log_file.fd;
- 清零全局變量ngx_cycle,并為ngx_cycle.pool創建大小為1024B的內存池;
- 調用ngx_save_argv()保存命令行參數至全局變量ngx_os_argv、ngx_argc、ngx_argv中;
- 調用ngx_process_options()初始化ngx_cycle的prefix, conf_prefix, conf_file, conf_param等字段;
- 調用ngx_os_init()初始化系統相關變量,如內存頁面大小ngx_pagesize,ngx_cacheline_size,最大連接數ngx_max_sockets等;
- 調用ngx_crc32_table_init()初始化CRC表(后續的CRC校驗通過查表進行,效率高);
- 調用ngx_add_inherited_sockets()繼承sockets;
- 解析環境變量NGINX_VAR="NGINX"中的sockets,并保存至ngx_cycle.listening數組;
- 設置ngx_inherited=1;
- 調用ngx_set_inherited_sockets()逐一對ngx_cycle.listening數組中的sockets進行設置;
- 具體可參考<nginx源碼分析—初始化過程中處理繼承的sockets>
- 初始化每個module的index,并計算ngx_max_module;具體可參考<nginx源碼分析—模塊及其初始化>;
- 調用ngx_init_cycle()進行初始化;
- 具體可參考<nginx源碼分析—全局變量ngx_cycle的初始化>;
- 若有信號,則進入ngx_signal_process()處理;
- 調用ngx_init_signals()初始化信號;主要完成信號處理程序的注冊;
- 若無繼承sockets,且設置了守護進程標識,則調用ngx_daemon()創建守護進程;
- 調用ngx_create_pidfile()創建進程記錄文件;(非NGX_PROCESS_MASTER=1進程,不創建該文件)
- 進入進程主循環;
- 若為NGX_PROCESS_SINGLE=1模式,則調用ngx_single_process_cycle()進入進程循環;
- 否則為master-worker模式,調用ngx_master_process_cycle()進入進程循環;
- 具體可參考<nginx源碼分析—master/worker進程啟動>;
簡要的函數調用圖如下。具體的還是需要閱讀源代碼。圖的自動生成,可參考<用Graphviz可視化函數調用-使用開源軟件來簡化復雜調用結構>。

2. 注意問題
2.1 幾個初值
- 00353: ngx_cycle = cycle; /* cycle是調用ngx_init_cycle()的返回值,而調用該函數的參數也是ngx_cycle */
- 00354:
- 00355: ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
- 00356:
- 00357: if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { /* ccf->master=-1 */
- 00358: ngx_process = NGX_PROCESS_MASTER;
- 00359: }
此處單獨將該段代碼拿出來,說明以下問題。 ngx_process在此處的值是什么?——NGX_PROCESS_SINGLE=0
ccf->master在此處的值之什么?——NGX_CONF_UNSET=-1
ngx_prefix何時初始化的?——ngx_log_init()中初始化
(1)ccf->master
ccf->master的值是在ngx_init_cycle()函數中調用NGX_CORE_MODULE模塊的create_conf鉤子(callback)完成初始化的。
具體可參考<nginx源碼分析—core模塊callback>。
(2)ngx_process
ngx_process是全局變量,定義如下。
- //./src/os/unix/ngx_process_cycle.c
- ngx_uint_t ngx_process;
- ngx_pid_t ngx_pid;
- ngx_uint_t ngx_threaded;
其在ngx_init_cycle()中沒有被初始化,故其初值為0。
(3)ngx_prefix
- static u_char *ngx_prefix; /* nginx工作目錄,默認為/usr/local/nginx/ */
- static u_char *ngx_conf_file; /* 配置文件 */
- static u_char *ngx_conf_params; /* nginx指令 */
在ngx_log_init()中初始化。 實際上,在main()函數開始調用的ngx_get_options()函數,即是處理nginx啟動的命令,并從中獲取參數并賦予相應的變量。
-p:ngx_prefix
-c:ngx_conf_file
-g:ngx_conf_params
-s:ngx_signal
關于這一點,可從以下命令結果看出端倪。
- # ./nginx -h
- nginx: nginx version: nginx/1.0.4
- nginx: Usage: nginx [-?hvVtq] [-s signal] [-c filename] [-p prefix] [-g directives]
-
- Options:
- -?,-h : this help
- -v : show version and exit
- -V : show version and configure options then exit
- -t : test configuration and exit
- -q : suppress non-error messages during configuration testing
- -s signal : send signal to a master process: stop, quit, reopen, reload
- -p prefix : set prefix path (default: /usr/local/nginx/)
- -c filename : set configuration file (default: conf/nginx.conf)
- -g directives : set global directives out of configuration file
2.2 nginx工作模式
因此,main()函數返回前調用ngx_master_process_cycle()函數進入多進程(master/worker)工作模式。如下。
- 00401: if (ngx_process == NGX_PROCESS_SINGLE) { /* 單進程 */
- 00402: ngx_single_process_cycle(cycle);
- 00403:
- 00404: } else { /* 多進程 */
- 00405: ngx_master_process_cycle(cycle);
- 00406: }
具體請參考<nginx源碼分析—master/worker進程啟動>。 2.3 一些配置
看源代碼時,會注意到有些宏(宏全部大寫,中間用下劃線隔開,這是nginx代碼規范。實際上,絕大多數系統均采用此規范)找不到定義,例如NGX_PREFIX、NGX_CONF_PREFIX、NGX_CONF_PATH等。
實際上,這些宏定義由configure程序進行自動配置時生成。配置時會自動生成ngx_auto_config.h文件(如果你用source insight閱讀源代碼,需要將該文件加入工程),如下。
./objs/ngx_auto_config.h(此處列出其中一部分常用的宏,未按順序)
- #ifndef NGX_COMPILER
- #define NGX_COMPILER "gcc 4.6.1 20110908 (Red Hat 4.6.1-9) (GCC) "
- #endif
-
- #ifndef NGX_PCRE
- #define NGX_PCRE 1
- #endif
-
- #ifndef NGX_PREFIX
- #define NGX_PREFIX "/usr/local/nginx/"
- #endif
-
- #ifndef NGX_CONF_PREFIX
- #define NGX_CONF_PREFIX "conf/"
- #endif
-
- #ifndef NGX_CONF_PATH
- #define NGX_CONF_PATH "conf/nginx.conf"
- #endif
-
- #ifndef NGX_PID_PATH
- #define NGX_PID_PATH "logs/nginx.pid"
- #endif
-
- #ifndef NGX_LOCK_PATH
- #define NGX_LOCK_PATH "logs/nginx.lock"
-
- #ifndef NGX_ERROR_LOG_PATH
- #define NGX_ERROR_LOG_PATH "logs/error.log"
- #endif
-
- #ifndef NGX_HTTP_LOG_PATH
- #define NGX_HTTP_LOG_PATH "logs/access.log"
- #endif
-
- #ifndef NGX_HTTP_CLIENT_TEMP_PATH
- #define NGX_HTTP_CLIENT_TEMP_PATH "client_body_temp"
- #endif
-
- #ifndef NGX_HTTP_PROXY_TEMP_PATH
- #define NGX_HTTP_PROXY_TEMP_PATH "proxy_temp"
- #endif
2.4 其他開關
還有一些開關,如NGX_FREEBSD, NGX_PCRE,NGX_OPENSSL等,這些宏也在configure過程中自動配置。nginx啟動時會根據這些宏是否定義調用相應的函數。此處非本文重點,不再贅述。
以上3個宏分別調用相應函數進行debug的初始化、正則表達式初始化和SSL的初始化。如下。(代碼未按順序)
- #if (NGX_FREEBSD)
- ngx_debug_init();
- #endif
-
- #if (NGX_PCRE)
- ngx_regex_init();
- #endif
-
- #if (NGX_OPENSSL)
- ngx_ssl_init(log);
-
- #endif
3. 小結
本文簡單分析nginx的啟動過程,后文繼續分析其中的ngx_init_cycle()和master/worker工作模型。
Reference
http://www.tbdata.org/archives/1092
http://www.w3.org/TR/PNG (CRC相關)
Nginx代碼研究計劃 (RainX1982)
nginx源碼分析—模塊及其初始化 (阿波)
nginx源碼分析—內存池結構ngx_pool_t及內存管理 (阿波)
nginx源碼分析—數組結構ngx_array_t (阿波)
nginx源碼分析—鏈表結構ngx_list_t (阿波)
nginx源碼分析—隊列結構ngx_queue_t (阿波)
nginx源碼分析—模塊及其初始化 (阿波)
nginx源碼分析—內存池結構ngx_pool_t及內存管理 (阿波)
nginx源碼分析—數組結構ngx_array_t (阿波)
nginx源碼分析—鏈表結構ngx_list_t (阿波)
nginx源碼分析—隊列結構ngx_queue_t (阿波)
nginx源碼分析—hash結構ngx_hash_t(v1.0.4) (阿波)