nginx有一套設計良好的源碼,以供分析,本文從ngx_module_t
結構體來分析nginx源碼結構。ngx_module_t
是整個nginx的關鍵,它提供了整個nginx的模塊化的基礎。所以,看懂ngx_module_t
結構體才能開始入門nginx源碼閱讀。nginx
ngx_module_t
結構體介紹該結構體描述了整個模塊的全部信息,爲核心模塊進行初始化和調用提供了接口,整個結構體的初始化源碼以下:模塊化
struct ngx_module_s { ngx_uint_t ctx_index; ngx_uint_t index; char *name; ngx_uint_t spare0; ngx_uint_t spare1; ngx_uint_t version; const char *signature; void *ctx; ngx_command_t *commands; ngx_uint_t type; ngx_int_t (*init_master)(ngx_log_t *log); ngx_int_t (*init_module)(ngx_cycle_t *cycle); ngx_int_t (*init_process)(ngx_cycle_t *cycle); ngx_int_t (*init_thread)(ngx_cycle_t *cycle); void (*exit_thread)(ngx_cycle_t *cycle); void (*exit_process)(ngx_cycle_t *cycle); void (*exit_master)(ngx_cycle_t *cycle); uintptr_t spare_hook0; uintptr_t spare_hook1; uintptr_t spare_hook2; uintptr_t spare_hook3; uintptr_t spare_hook4; uintptr_t spare_hook5; uintptr_t spare_hook6; uintptr_t spare_hook7; };
ngx_module_s
的關鍵部分在於中間的幾個函數指針,以ngx_core_module
核心模塊爲例:函數
ngx_module_t ngx_core_module = { NGX_MODULE_V1, &ngx_core_module_ctx, /* module context */ ngx_core_commands, /* module directives */ NGX_CORE_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING };
關於NGX_MODULE_V1
和NGX_MODULE_V1_PADDING
2個關鍵字是2個宏定義,主要用於快速聲明而已,剩下的屬性能夠分爲4類:模塊類型、模塊命令、模塊上下文、預留接口。咱們能夠先了解模塊命令結構體(ngx_command_s)工具
ngx_command_s
結構體是用來分析整個配置文件關鍵字的工具,源碼以下:post
struct ngx_command_s { ngx_str_t name; ngx_uint_t type; char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); ngx_uint_t conf; ngx_uint_t offset; void *post; };
ngx_module_t
結構體接口位置init_master
接口字面意思是初始化master
進程時候進行調用,可是暫未找到接口位置。學習
init_module
接口該接口是在模塊初始化的時候調用,調用位置在於ngx_init_cycle>ngx_init_modules
的代碼中:ui
ngx_int_t ngx_init_modules(ngx_cycle_t *cycle) { ngx_uint_t i; for (i = 0; cycle->modules[i]; i++) { if (cycle->modules[i]->init_module) { if (cycle->modules[i]->init_module(cycle) != NGX_OK) { return NGX_ERROR; } } } return NGX_OK; }
init_process
接口該接口分別在ngx_worker_process_init
和ngx_single_process_cycle
,2者會在不一樣的模式下運行,因此只會初始化一次。咱們以多進程模式爲例,其路徑在:ngx_master_process_cycle>ngx_start_worker_processes>ngx_worker_process_cycle
,關鍵代碼以下:spa
static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker) { ... ... for (i = 0; cycle->modules[i]; i++) { if (cycle->modules[i]->init_process) { if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) { /* fatal */ exit(2); } } } ... ... }
init_thread
接口字面意思是初始化線程進程時候進行調用,可是暫未找到接口位置。線程
exit_thread
接口字面意思是退出線程進程時候進行調用,可是暫未找到接口位置。debug
exit_process
接口該接口於init_process
接口對應,其路徑在:ngx_master_process_cycle>ngx_start_worker_processes>ngx_worker_process_exit
,條件是在出現中斷,或者沒有時間片的時候退出線程並調用。關鍵代碼以下:
static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) { ngx_int_t worker = (intptr_t) data; ngx_process = NGX_PROCESS_WORKER; ngx_worker = worker; ngx_worker_process_init(cycle, worker); ngx_setproctitle("worker process"); for ( ;; ) { if (ngx_exiting) { if (ngx_event_no_timers_left() == NGX_OK) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); ngx_worker_process_exit(cycle); } } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); ngx_process_events_and_timers(cycle); if (ngx_terminate) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); ngx_worker_process_exit(cycle); } } ... ... }
exit_master
接口該接口是當master
進程退出時調用,其路徑在:ngx_master_process_cycle>ngx_master_process_exit
,關鍵代碼以下:
void ngx_master_process_cycle(ngx_cycle_t *cycle) { ... ... for ( ;; ) { ... ... if (!live && (ngx_terminate || ngx_quit)) { ngx_master_process_exit(cycle); } ... ... } }
等於當出現退出或中斷信號,或者進程再也不存活的時候,進行退出操做。
初次閱讀nginx
源碼,先從結構體開始學習,開篇之做,再接再礪。