Nginx 모듈 자체 개발 7: 소스 코드 분석 전체 Nginx 프레임 워 크

17228 단어 nginx
블 로그 에서 언급 한 Nginx 모듈 자체 개발 4: 모듈 데이터 구조 중요 한 데이터 구조 ngxmodule_s, 모든 모듈 은 이 구조 체 로 표 시 됩 니 다.
ngx_module_t 구조 체
모듈 은 또 ngx 로 나 뉜 다.core_module_t 와 ngxxxx_module_t, 그리고 ngxmodule_t 에는 이 두 가지 구조 가 포함 되 어 있 습 니 다. 서로 다른 유형의 모듈 은 서로 다른 구 조 를 포함 하고 보통 ctx 로 'ngx' 를 표시 합 니 다.module_t 는 type 이 도 메 인 으로 모듈 의 종 류 를 표시 합 니 다.
struct ngx_module_s {
   /*ctx_index               。                 Nginx       ,     http    ,ctx_index      ngx_http_module   ,ctx_index    ,Nginx                 */
    ngx_uint_t            ctx_index;
    /*index       ngx_modules       。*/
    ngx_uint_t            index; 

    char                 *name;
    // sqare        ,    
    ngx_uint_t            spare0;
    ngx_uint_t            spare1;
    //      
    ngx_uint_t            version;
    const char           *signature;
   /**ctx                ,Nginx       ,             。          I/O       ,           ,ctx               ,   Http     ,ctx  ngx_http_module_t   */
    void                 *ctx;
    // commands   nginx.conf      
    ngx_command_t        *commands;
    /*type         ,  ctx        ,NGX_HTTP_MODULE、NGX_CORE_MODULE、NGX_CONF_MODULE、NGX_EVENT_MODULE、NGX_EVENT_MODULE、NGX_STREAM_MODULE*/
    ngx_uint_t            type;
    /* Nginx   、     ,  7        7          7   ,      ,     Nginx         ,          NULL      */
    /*           master       ,      ,           ,      NULL*/
    ngx_int_t           (*init_master)(ngx_log_t *log);
    /*init module                , master/worker   ,      worker      */
    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);
   /*init_process             , master/worker   ,  worker       ,   worker             init_process  */
    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);
    // Nginx        ,          
    ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);
    void                (*exit_thread)(ngx_cycle_t *cycle);
   /* exit_process            。 master/worker   ,worker        */
    void                (*exit_process)(ngx_cycle_t *cycle);
    //      master        
    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;
};

여기 에는 두 개의 index 가 있 는데, 각각 ctx 이다.index 와 index, 그들의 차 이 는 이렇다 (http 모듈 로 예 를 들 면), ctxindex 는 http module 의 config 색인 을 저장 하고 모든 http module config 는 nginx 에 저 장 됩 니 다.conf_t 의 ctx 배열 에 있 습 니 다. index 는 모든 core module 의 config 색인 을 저장 하고 모든 core module 의 config 는 cycle 에 저 장 된 config 입 니 다.ctx 에서 아래 코드 를 쉽게 볼 수 있 습 니 다.
#define ngx_http_conf_get_module_main_conf(cf, module)                        
    ((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]

#define ngx_get_conf(conf_ctx, module)  conf_ctx[module.index]

ngx_core_module_t 는 모두 (log, event, event openssl, http, mail, google perftools) 를 포함 하고 http module 자체 도 core module 임 을 볼 수 있 습 니 다.여기 에는 또 하나의 conf module 이 있 는데, 단지 그것 도 core module 이라는 데이터 구 조 를 사용 하 는 것 임 을 주의해 야 한다.
typedef struct {
    ngx_str_t             name;
    void               *(*create_conf)(ngx_cycle_t *cycle);
    char               *(*init_conf)(ngx_cycle_t *cycle, void *conf);
} ngx_core_module_t;

ngx_http_module_t 는 모든 src / http / 아래 모듈 을 포함 하고 http module 을 포함 하 며 http core 모듈 에 속 합 니 다.
typedef struct {
    ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);
    ngx_int_t   (*postconfiguration)(ngx_conf_t *cf);

    void       *(*create_main_conf)(ngx_conf_t *cf);
    char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);

    void       *(*create_srv_conf)(ngx_conf_t *cf);
    char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);

    void       *(*create_loc_conf)(ngx_conf_t *cf);
    char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;

또 하나의 ngxmodule_s 또 하나의 중요 한 멤버 는 ngxcommand_t。이 도 메 인 은 현재 모듈 에 포 함 된 모든 명령 을 포함 합 니 다.
위의 데이터 구 조 를 분석 한 다음 에 전체 Nginx 프레임 워 크 의 방향 을 전체적으로 분석 할 것 입 니 다. 앞의 블 로그 Nginx 모듈 은 자체 개발 6: 소스 분석 프로필 분석 과정 에서 ngx 를 상세 하 게 소개 합 니 다.init_cycle 의 절차, 이 블 로 그 는 주로 ngxinit_cycle 는 모든 모듈 의 절 차 를 어떻게 연결 하 는 지 말 합 니 다.(일부 부분 은 중복 되 지만 전체 Nginx 프레임 워 크 의 절 차 를 정리 하기 위해 서 는 가치 가 있 습 니 다)
Nginx 는 ngxinit_cycle 에 서 는 다음 코드 를 통 해 모든 configure 를 만 듭 니 다. 각각 core module 의 Create 를 호출 합 니 다.conf 방법 으로 대응 하 는 conf 를 만 듭 니 다. 대상 마다 전역 에 저 장 된 confctx 중.
/*
                    。Nginx     NGX_CORE_MODULE 
   ,             。             create conf  (             ),           
                 。           ?     。               ,   HTTP    ngx_http_module
  (  8-2  ),  ngx_http_module         “http”    ,      HTTP                   
(xxx_create_main_conf、xxx_create_srv_conf、xxx_create_loc_conf  )。
*/
    for (i = 0; cycle->modules[i]; i++) {
        if (cycle->modules[i]->type != NGX_CORE_MODULE) {
            continue;
        }
    //  core module
        module = cycle->modules[i]->ctx;
     /  create_conf  ,     config
        if (module->create_conf) {
            rv = module->create_conf(cycle);
            if (rv == NULL) {
                ngx_destroy_pool(pool);
                return NULL;
            }
            cycle->conf_ctx[cycle->modules[i]->index] = rv;  
        }
    }
       .......
    conf.ctx = cycle->conf_ctx;  //     ngx_conf_param       ,   conf.ctx    ,      cycle->conf_ctx[i]
    conf.cycle = cycle;
    conf.pool = pool;
    conf.log = log;
    conf.module_type = NGX_CORE_MODULE;
    conf.cmd_type = NGX_MAIN_CONF;

모든 core module 의 config 가 생 성 되면 프로필 을 분석 해 야 합 니 다. 프로필 을 분석 하면 한 줄 씩 읽 고 명령 을 받 으 면 해당 하 는 ngx 를 찾 을 수 있 습 니 다.command_t 대상, 그리고 대응 하 는 반전 set 방법 을 실행 합 니 다.여기 모든 동작 이 ngxconf_parse 이 함수 에서 진행 합 니 다.그리고 ngxconf_parse 는 cf 에 handler 반전 이 있 는 지 판단 합 니 다. 있 으 면 handler 반전 을 우선 호출 하고 없 으 면 ngx 에 들 어 갑 니 다.conf_handler 일반 처리.일반적으로 사용자 정의 handler 가 없 으 면 파일 을 분석 하 는 과정 ngx_init_cycle()->ngx_conf_parse()->ngx_conf_handler() 을 분석 하고 마지막 으로 cmd - > set 방법 으로 리 셋 합 니 다.이때 우리 ngxcommand_t 설정 의 반전 함수.예컨대, ngxhttp. c 의 ngxhttp_block 함수.
//     ngx_http.c ngx_http_bock  
//         ctx     ,   main,serv conf      ,          
for (m = 0; cf->cycle->modules[m]; m++) {
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = cf->cycle->modules[m]->ctx; //   module      ngx_module_t   ctx
        mi = cf->cycle->modules[m]->ctx_index; //       
     //        ,       ,        config   ctx    conf   
        if (module->create_main_conf) {  
            ctx->main_conf[mi] = module->create_main_conf(cf);
            if (ctx->main_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }

        if (module->create_srv_conf) { // 
            ctx->srv_conf[mi] = module->create_srv_conf(cf);
            if (ctx->srv_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }

        if (module->create_loc_conf) { //
            ctx->loc_conf[mi] = module->create_loc_conf(cf);
            if (ctx->loc_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }
    }
    ....
    //     
    rv = ngx_conf_parse(cf, NULL);

http module 관련 config 는 ngxhttp_block 에서 만 든, ngxhttp_block 에서 생 성, 초기 화, config 통합, http handler phase 전체 초기 화 등 이 있 습 니 다. 먼저 http module 의 ctx 를 초기 화 합 니 다.index. http block 이 완전히 parse 가 끝 난 후에 merge (main 과 srv 또는 srv 와 loc) 와 관련 된 config 가 필요 합 니 다.하지만 매번 merge 전에 main conf 를 먼저 초기 화 합 니 다.
  cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
    cscfp = cmcf->servers.elts;

    for (m = 0; cf->cycle->modules[m]; m++) {
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = cf->cycle->modules[m]->ctx;
        mi = cf->cycle->modules[m]->ctx_index;

        /* init http{} main_conf's */

        if (module->init_main_conf) {
            rv = module->init_main_conf(cf, ctx->main_conf[mi]);
            if (rv != NGX_CONF_OK) {
                goto failed;
            }
        }
     //    merge config。
     /*            ctx(main/ser/loc),    ,     HTTP main    3 ctx(main/srv/loc),  HTTP srv block     2 ctx(srv/loc),       ,    merge 。      (srv_offset) HTTP main    ,  Nginx       HTTP main ctx srv ctx ,  server block    ,  Nginx       Server ctx  srv_conf ,  merge  。*/
        rv = ngx_http_merge_servers(cf, cmcf, module, mi);//  server{}     local{}
        if (rv != NGX_CONF_OK) {
            goto failed;
        }

merge 가 끝 난 후에 location 의 처리 입 니 다. location tree 를 초기 화하 고 handler phase 를 만 들 며 post configuration 을 호출 하고 변수의 초기 화 입 니 다.
    /*
             ,  server     http core   main    servers   ,   server   location      
            http core   loc   locations   ,          server location         ,   
        ngx_http_init_location()   :
    */
      /*location      */
       if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
            return NGX_CONF_ERROR;
        }
/*          location           ,             。 ngx_http_init_locations    ,           
          */
        /*
           ngx_http_init_static_location_trees          location(  ngx_http_init_locations name noname regex   location(exact/inclusive)),
         staticlocation,    (     )  ,          ,      http             location  。
        */

        if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
            return NGX_CONF_ERROR;
        }
    }

  //   handler phase
    if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }
   for (m = 0; ngx_modules[m]; m++) {
        if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = ngx_modules[m]->ctx;
//    
        if (module->postconfiguration) {
            if (module->postconfiguration(cf) != NGX_OK) {
                return NGX_CONF_ERROR;
            }
        }
    }
//       
    if (ngx_http_variables_init_vars(cf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

위의 작업 을 마 친 후, 아래 는 socket 과 관련 된 것 을 초기 화 합 니 다. 예 를 들 어 읽 기와 쓰기 반전 함수 설정 등 입 니 다.

    if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }


    /* optimize the lists of ports, addresses and server names */

    if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

ngx_cycle_init 남 은 부분 은 프로필 분석 이 끝나 면 core module 의 config 를 초기 화 합 니 다.
for (i = 0; cycle->modules[i]; i++) {
        if (cycle->modules[i]->type != NGX_CORE_MODULE) {
            continue;
        }

        module = cycle->modules[i]->ctx;

        if (module->init_conf) {
            if (module->init_conf(cycle,
                                  cycle->conf_ctx[cycle->modules[i]->index])
                == NGX_CONF_ERROR)
            {
                environ = senv;
                ngx_destroy_cycle_pools(&conf);
                return NULL;
            }
        }
    }

다음은 만 든 모든 공유 메모 리 를 만 들 고 초기 화 하 는 것 입 니 다.
  if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) {
            goto failed;
        }

        if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) {
            goto failed;
        }

        if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) {
            goto failed;
        }

다음은 감청 을 켜 고 모든 모듈 을 초기 화 하 는 것 입 니 다.
.....
if (ngx_open_listening_sockets(cycle) != NGX_OK) {
    goto failed;
}
....
  //         
    if (ngx_init_modules(cycle) != NGX_OK) {
        /* fatal */
        exit(1);
    }

그때 까지 ngxinit_cycle () 함수 의 주요 작업 이 모두 완성 되 었 습 니 다.
총결산
Nginx 모듈 과 프레임 간 의 협업 을 분명히 하려 면 ngx 뿐만 아니 라command_t 구조 체, ngxmodule_t 구조 체, ngxconf_t 구조 및 ngxcycle_t 구조 체 의 관 계 는 리 턴 방법 으로 전체 절 차 를 분석 하 는 것 도 배 워 야 한다.위 에서 보면 ngxhttp_Block 함수 의 location 초기 화 는 자세히 전개 되 지 않 았 습 니 다. mail 과 stream 에 서 는 이 단계 가 없 기 때문에 나중에 자세히 알 아 보 겠 습 니 다.

좋은 웹페이지 즐겨찾기