分析Nginx 源碼 - ngx_module_t接口總結

關於

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_V1NGX_MODULE_V1_PADDING2個關鍵字是2個宏定義,主要用於快速聲明而已,剩下的屬性能夠分爲4類:模塊類型、模塊命令、模塊上下文、預留接口。咱們能夠先了解模塊命令結構體(ngx_command_s)工具

模塊命令結構體(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_initngx_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源碼,先從結構體開始學習,開篇之做,再接再礪。

相關文章
相關標籤/搜索