主要介紹Nginx的啟動過程,可以在/core/nginx.c中找到Nginx的主函式main(),那麼就從這裡開始分析Nginx的啟動過程。
涉及到的基本函式
原始碼:
Nginx的啟動包括了很多的初始化和處理函式。這些函式相對來說,有一部分非常複雜,暫且從簡單開始,從整體上對Ngixnd的啟動有一個瞭解,方便日後的分析與學習。
主要函式:
static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
//對引數選項進行處理
static ngx_int_t ngx_get_options(int argc, char *const *argv);
//初始化ngx_cycle內的部分內容
static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
//命令列引數儲存到ngx_os_argv、ngx_argc以及ngx_argv全域性的變數中
static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv); //建立模組的配置資訊
static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
//初始化配置資訊
static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf);
static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
//設定優先順序
static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
//設定CPU親和性
static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
//設定worker程式
static char *ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
Nginx啟動的主要流程
下圖為Nginx的啟動時函式的呼叫過程,其中大部分都是為了Nginx啟動的初始化部分。從錯誤處理、引數設定、時間設定等方面進行初始化,並註冊了我們需要的模組,最後根據訊號選擇單任務模式還是master-worker模式。
流程圖:
初始化
主函式在開始對系統錯誤、引數、時間、系統變數、日誌等進行了初始化。
ngx_strerror_init();
//對引數選項進行處理
ngx_get_options(argc, argv);
//時間初始化
ngx_time_init();
//重置pcre記憶體管理的介面
ngx_regex_init();
//日誌初始化
ngx_log_init(ngx_prefix);
//建立記憶體池
ngx_create_pool(1024, log);
//儲存變數
ngx_save_argv();
//初始化ngx_cycle的prefix, conf_prefix, conf_file, conf_param
ngx_process_options();
//初始化系統相關變數,如記憶體頁面大小,ngx_pagesize,ngx_cacheline_size,最大連線數ngx_max_sockets等
ngx_os_init();
//初始化CRC表(後續的CRC校驗通過查表進行,效率高)
ngx_crc32_table_init();
主要工作
初始化完成後,需要先呼叫ngx_add_inherited_sockets函式繼承socket,並儲存在Listening陣列中,在執行時候進行監聽。之後就可以呼叫ngx_init_cycle來初始化ngx_cycle結構體,這個結構體用來儲存所有的連線,具體如下:
ngx_connection_t **files; //連線檔案
ngx_connection_t *free_connections; //空閒連線
ngx_uint_t free_connection_n; //空閒連線數
ngx_queue_t reusable_connections_queue;////再利用連線佇列
ngx_array_t listening; //監聽陣列
ngx_array_t paths; //路徑陣列
ngx_list_t open_files; //開啟檔案連結串列
ngx_list_t shared_memory; //共享記憶體連結串列
ngx_uint_t connection_n; //連線個數
ngx_uint_t files_n; //開啟檔案個數
ngx_connection_t *connections;
ngx_event_t *read_events; //讀事件
ngx_event_t *write_events; //寫事件
ngx_cycle_t *old_cycle; ngx_str_t conf_file; //配置檔案
ngx_str_t conf_param; //配置引數
ngx_str_t conf_prefix; //配置字首
ngx_str_t prefix; //字首
ngx_str_t lock_file; //鎖檔案
ngx_str_t hostname;
呼叫ngx_init_signals來註冊訊號。
//訊號種類
#define NGX_PROCESS_SINGLE 0
#define NGX_PROCESS_MASTER 1
#define NGX_PROCESS_SIGNALLER 2
#define NGX_PROCESS_WORKER 3
#define NGX_PROCESS_HELPER 4
在進入處理之前,還要呼叫ngx_create_pidfile來記錄程式id。最後,根據接收到的訊號,來判斷呼叫ngx_single_process_cycle還是ngx_master_process_cycle(master-worker模式)。
if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); }
其中,守護程式函式為ngx_daemon,位於src/os/unix/Ngx_daemon.c
參考
http://blog.xiuwz.com/2011/11/29/nginx-pcre-conflict/
http://blog.csdn.net/liuhongxiangm/article/details/8107613
http://www.4os.org/index.php/2010/11/25/nginx%E5%90%AF%E5%8A%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E8%BF%87%E7%A8%8B%E8%BD%AC%E8%BD%BD/
http://blog.csdn.net/livelylittlefish/article/details/7243718