Nginx 모듈 자체 개발 7: 소스 코드 분석 전체 Nginx 프레임 워 크
17228 단어 nginx
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 에 서 는 이 단계 가 없 기 때문에 나중에 자세히 알 아 보 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
간단! Certbot을 사용하여 웹 사이트를 SSL(HTTPS)화하는 방법초보자가 인프라 주위를 정돈하는 것은 매우 어렵습니다. 이번은 사이트를 간단하게 SSL화(HTTP에서 HTTPS통신)로 변경하는 방법을 소개합니다! 이번에는 소프트웨어 시스템 Nginx CentOS7 의 환경에서 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.