nginx 소스 코드 분석 - 프로필 분석
우선 설정 해석 시의 데이터 구 조 를 살 펴 보 겠 습 니 다. 여 기 는 주로 ngx 입 니 다.conf_t. 이 구 조 는 설정 파일 을 분석 하 는 데 필요 한 도 메 인 을 저장 합 니 다. 이것 은 매우 중요 한 데이터 구조 입 니 다. 우 리 는 이 구 조 를 자세히 살 펴 보 겠 습 니 다.
struct ngx_conf_s {
//
char *name;
//
ngx_array_t *args;
// cycle
ngx_cycle_t *cycle;
//
ngx_pool_t *pool;
// pool 。
ngx_pool_t *temp_pool;
//
ngx_conf_file_t *conf_file;
// log
ngx_log_t *log;
// ( )
void *ctx;
//
ngx_uint_t module_type;
//
ngx_uint_t cmd_type;
// handler
ngx_conf_handler_pt handler;
// handler conf
char *handler_conf;
};
위의 일부 도 메 인 은 아직 이해 하지 못 할 수도 있 지만 괜찮아 요. 그 다음 에 하나씩 분석 할 거 예요.
설정 해석 의 입 구 를 살 펴 보 겠 습 니 다. 입 구 는 ngx 입 니 다.init_cycle 에서 여 기 는 비교적 간단 합 니 다. 바로 ngx 를 설정 하 는 것 입 니 다.conf_t 그리고 ngx 에 게 전달conf_parse 해석.
// conf_ctx
cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
if (cycle->conf_ctx == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
.............................................
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = ngx_modules[i]->ctx;
if (module->create_conf) {
rv = module->create_conf(cycle);
if (rv == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
// conf_ctx main conf.
cycle->conf_ctx[ngx_modules[i]->index] = rv;
}
}
.................................
// conf
conf.ctx = cycle->conf_ctx;
conf.cycle = cycle;
conf.pool = pool;
conf.log = log;
// , MAIN, core。
conf.module_type = NGX_CORE_MODULE;
conf.cmd_type = NGX_MAIN_CONF;
if (ngx_conf_param(&conf) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
//
if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
그리고 ngxconf_parse, 이 함수 의 두 번 째 는 분석 할 파일 이름 입 니 다. 그러나 여기 서 주의해 야 할 것 은 두 번 째 매개 변 수 는 비어 있 을 수 있 습 니 다. 비어 있 으 면 block 의 내용 이나 param 을 분석 할 것 입 니 다.
char *
ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
{
char *rv;
ngx_fd_t fd;
ngx_int_t rc;
ngx_buf_t buf;
ngx_conf_file_t *prev, conf_file;
enum {
parse_file = 0,
parse_block,
parse_param
} type;
#if (NGX_SUPPRESS_WARN)
fd = NGX_INVALID_FILE;
prev = NULL;
#endif
if (filename) {
/* open configuration file */
................................................
} else if (cf->conf_file->file.fd != NGX_INVALID_FILE) {
// block
type = parse_block;
} else {
//
type = parse_param;
}
for ( ;; ) {
rc = ngx_conf_read_token(cf);
/*
* ngx_conf_read_token() may return
*
* NGX_ERROR there is error
* NGX_OK the token terminated by ";" was found
* NGX_CONF_BLOCK_START the token terminated by "{" was found
* NGX_CONF_BLOCK_DONE the "}" was found
* NGX_CONF_FILE_DONE the configuration file is done
*/
.....................................................
/* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */
// handler, handle
if (cf->handler) {
/*
* the custom handler, i.e., that is used in the http's
* "types { ... }" directive
*/
rv = (*cf->handler)(cf, NULL, cf->handler_conf);
if (rv == NGX_CONF_OK) {
continue;
}
if (rv == NGX_CONF_ERROR) {
goto failed;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);
goto failed;
}
// handler
rc = ngx_conf_handler(cf, rc);
if (rc == NGX_ERROR) {
goto failed;
}
}
failed:
rc = NGX_ERROR;
done:
....................................
return NGX_CONF_OK;
}
보고 있어 ngxconf_handler 전에 Nginx 프로필 의 구조 와 cf - > handler 가 왜 있 는 지 살 펴 보 겠 습 니 다.
일반적인 Nginx 프로필 은 다음 과 같 습 니 다:
worker_processes 1;
error_log logs/error.log;
pid logs/nginx.pid;
events { worker_connections 1024; }
http { include mime.types; default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
#gzip on;
server { listen 80; server_name localhost;
access_log logs/host.access.log main;
location / { root html; index index.html index.htm; }
error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
}
Nginx 의 설정 파일 이 블록 으로 나 뉘 어 져 있 는 것 을 볼 수 있 습 니 다. 그리고 이벤트, http 는 모두 큰 core 모듈 입 니 다. 그리고 core 모듈 에는 2 급 모듈 (epoll / kqeue / proxy..) 이 많이 포함 되 어 있 습 니 다. 즉, 1 급 모듈 에는 2 급 모듈 의 설정 을 저장 하기 위 한 컨 텍스트 가 포함 되 어 있어 야 합 니 다.한편, HTTP 모듈 에 또 일부 특수 한 것 이 있 습 니 다. 그것 은 HTTP 모듈 에 있 는 모든 명령 에 3 개의 역할 영역 이 있 을 수 있 습 니 다. 그것 이 바로 main / server / loc 이기 때문에 HTTP 의 컨 텍스트 에 이 3 개의 컨 텍스트 를 동시에 저장 해 야 합 니 다.
그리고 Nginx 의 명령 은 모두 그런 유형 이 있 습 니 다.
#define NGX_DIRECT_CONF 0x00010000
#define NGX_MAIN_CONF 0x01000000
#define NGX_ANY_CONF 0x0F000000
#define NGX_EVENT_CONF 0x02000000
#define NGX_HTTP_MAIN_CONF 0x02000000
#define NGX_HTTP_SRV_CONF 0x04000000
#define NGX_HTTP_LOC_CONF 0x08000000
#define NGX_HTTP_UPS_CONF 0x10000000
#define NGX_HTTP_SIF_CONF 0x20000000
#define NGX_HTTP_LIF_CONF 0x40000000
#define NGX_HTTP_LMT_CONF 0x80000000
#define NGX_MAIL_MAIN_CONF 0x02000000
#define NGX_MAIL_SRV_CONF 0x04000000
Nginx 의 매개 변수 유형 은 이렇게 여러 가지 가 있 는데 그 중에서 가장 구분 해 야 할 것 은 첫 번 째 와 두 번 째 입 니 다. 일반적으로 DIRECTCONF 와 MAINCONF 는 첫 번 째 가 있 으 면 두 번 째 가 동시에 사용 된다.DIRECT_CONF 는 말 그대로 CONF 에 직접 액세스 한 다 는 것 이다. 즉, 명령 해석 함수 에 들 어가 면서 CONF 가 만 들 어 졌 으 니 직접 사용 하면 된다 는 것 이다. (즉, create conf 리 셋 이 있 을 것 이다) Main conf 는 맨 위 에 있 는 conf, 예 를 들 어 HTTP / EVENT / PID 등 은 모두 CORE 모듈 에 속 하 는 것 을 볼 수 있다. NGX HTTP XXX 는 모든 HTTP 모듈 의 하위 모듈 이다.
Nginx 설정 의 기본 구 조 를 이 해 했 습 니 다. ngx conf handler 를 살 펴 보 겠 습 니 다. 이 함 수 는 예전 에 소 개 했 습 니 다. 이번 에는 가장 핵심 적 인 부분 에 만 관심 을 가지 고 있 습 니 다. 아래 부분 은 명령 표를 옮 겨 다 니 며 해당 하 는 명령 을 찾 은 다음 에 처리 합 니 다.
// type
if (!(cmd->type & NGX_CONF_ANY)) {
//
if (cmd->type & NGX_CONF_FLAG) {
if (cf->args->nelts != 2) {
goto invalid;
}
} else if (cmd->type & NGX_CONF_1MORE) {
if (cf->args->nelts < 2) {
goto invalid;
}
.................................................
}
/* set up the directive's configuration context */
conf = NULL;
// ,
if (cmd->type & NGX_DIRECT_CONF) {
ctx core conf(create_conf ), conf.
conf = ((void **) cf->ctx)[ngx_modules[i]->index];
} else if (cmd->type & NGX_MAIN_CONF) {
// DIRECT_CONF MAIN, ( )
conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
} else if (cf->ctx) {
// ( )。
confp = *(void **) ((char *) cf->ctx + cmd->conf);
if (confp) {
conf = confp[ngx_modules[i]->ctx_index];
}
}
// 。
rv = cmd->set(cf, cmd, conf);
if (rv == NGX_CONF_OK) {
return NGX_OK;
}
if (rv == NGX_CONF_ERROR) {
return NGX_ERROR;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"%s\" directive %s", name->data, rv);
return NGX_ERROR;
}
위의 코드 에서 2 급 모듈 은 그 부분 을 분석 할 때 먼저 놓 습 니 다. 먼저 Nginx 에 2 급 모듈 이 있 는 1 급 모듈 이 명령 을 어떻게 해석 하 는 지, HTTP 모듈 (event 모듈 은 기본적으로 같 습 니 다) 의 분석 코드 를 보 겠 습 니 다.
// direct_conf, http 。
static ngx_command_t ngx_http_commands[] = {
{ ngx_string("http"),
NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_block,
0,
0,
NULL },
ngx_null_command
};
static char *
ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *rv;
ngx_uint_t mi, m, s;
ngx_conf_t pcf;
ngx_http_module_t *module;
ngx_http_conf_ctx_t *ctx;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t **cscfp;
ngx_http_core_main_conf_t *cmcf;
/* the main http context */
ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
if (ctx == NULL) {
return NGX_CONF_ERROR;
}
// , conf
*(ngx_http_conf_ctx_t **) conf = ctx;
/* count the number of the http modules and set up their indices */
ngx_http_max_module = 0;
for (m = 0; ngx_modules[m]; m++) {
if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
continue;
}
// .
ngx_modules[m]->ctx_index = ngx_http_max_module++;
}
/* the http main_conf context, it is the same in the all http contexts */
// HTTP conf, (main/ser/loc) conf.
ctx->main_conf = ngx_pcalloc(cf->pool,
sizeof(void *) * ngx_http_max_module);
if (ctx->main_conf == NULL) {
return NGX_CONF_ERROR;
}
/*
* the http null srv_conf context, it is used to merge
* the server{}s' srv_conf's
*/
ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
if (ctx->srv_conf == NULL) {
return NGX_CONF_ERROR;
}
/*
* the http null loc_conf context, it is used to merge
* the server{}s' loc_conf's
*/
ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
if (ctx->loc_conf == NULL) {
return NGX_CONF_ERROR;
}
/*
* create the main_conf's, the null srv_conf's, and the null loc_conf's
* of the all http modules
*/
....................................
// cf, HTTP cf,
pcf = *cf;
//
cf->ctx = ctx;
..........................................
/* parse inside the http{} block */
//
cf->module_type = NGX_HTTP_MODULE;
cf->cmd_type = NGX_HTTP_MAIN_CONF;
// ,
rv = ngx_conf_parse(cf, NULL);
if (rv != NGX_CONF_OK) {
goto failed;
}
/*
* init http{} main_conf's, merge the server{}s' srv_conf's
* and its location{}s' loc_conf's
*/
.........................................
/*
* http{}'s cf->ctx was needed while the configuration merging
* and in postconfiguration process
*/
// cf
*cf = pcf;
......................................
return NGX_CONF_OK;
failed:
*cf = pcf;
return rv;
}
여기 서 매우 중요 한 부분 이 있 습 니 다. 그것 은 각 단계 에 해당 하 는 ctx (main / ser / loc) 를 저장 하 는 것 입 니 다. 뭐라고 해 야 할 까요? HTTP main 을 분석 하 는 과정 에서 3 개의 ctx (main / srv / loc) 를 만 들 었 고, HTTP srv block 에 서 는 2 개의 ctx (main / srv / loc) 를 만 들 것 입 니 다. 중복 되 었 으 면 merge 가 필요 합 니 다. 예 를 들 어 명령 (srv offset) 이 필요 합 니 다.HTTP main 중 하나 입 니 다. 그러면 Nginx 는 HTTP main 의 ctx srv ctx 에 넣 고 server block 도 하나 있 습 니 다. 그러면 Nginx 는 Server ctx 의 srv conf 에 계속 넣 고 마지막 으로 merge 를 합 니 다.
그래서 server 라 는 명령 의 해석 을 살 펴 보 겠 습 니 다.
{ ngx_string("server"),
NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_MULTI|NGX_CONF_NOARGS,
ngx_http_core_server,
0,
0,
NULL },
static char *
ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{
char *rv;
void *mconf;
ngx_uint_t i;
ngx_conf_t pcf;
ngx_http_module_t *module;
struct sockaddr_in *sin;
ngx_http_conf_ctx_t *ctx, *http_ctx;
ngx_http_listen_opt_t lsopt;
ngx_http_core_srv_conf_t *cscf, **cscfp;
ngx_http_core_main_conf_t *cmcf;
ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
if (ctx == NULL) {
return NGX_CONF_ERROR;
}
http_ctx = cf->ctx;
//main conf
ctx->main_conf = http_ctx->main_conf;
/* the server{}'s srv_conf */
// srv loc conf.
ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
if (ctx->srv_conf == NULL) {
return NGX_CONF_ERROR;
}
/* the server{}'s loc_conf */
ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
if (ctx->loc_conf == NULL) {
return NGX_CONF_ERROR;
}
............................
/* the server configuration context */
cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
cscf->ctx = ctx;
cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
// servers, main 。 HTTP main srv conf.
cscfp = ngx_array_push(&cmcf->servers);
if (cscfp == NULL) {
return NGX_CONF_ERROR;
}
*cscfp = cscf;
/* parse inside server{} */
// , type srv_conf.
pcf = *cf;
cf->ctx = ctx;
cf->cmd_type = NGX_HTTP_SRV_CONF;
rv = ngx_conf_parse(cf, NULL);
// cf.
*cf = pcf;
........................
}
return rv;
}
이런 것들 을 알 게 되 었 습 니 다. 우 리 는 맨 위의 코드 를 보 겠 습 니 다.
struct ngx_command_s {
ngx_str_t name;
ngx_uint_t type;
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
//conf . NGX_HTTP_LOC_CONF_OFFSET
ngx_uint_t conf;
ngx_uint_t offset;
void *post;
};
............................
else if (cf->ctx) {
// 1 (HTTP srv_offset)
confp = *(void **) ((char *) cf->ctx + cmd->conf);
if (confp) {
// conf.
conf = confp[ngx_modules[i]->ctx_index];
}
}
그리고 간단 한 명령 을 어떻게 사용 하고 설정 하 는 지 살 펴 보 겠 습 니 다. 보기 전에 몇 가지 핵심 구 조 를 살 펴 보 겠 습 니 다.
typedef struct {
void **main_conf;
void **srv_conf;
void **loc_conf;
} ngx_http_conf_ctx_t;
// ngx_command_t conf , conf .
#define NGX_HTTP_MAIN_CONF_OFFSET offsetof(ngx_http_conf_ctx_t, main_conf)
#define NGX_HTTP_SRV_CONF_OFFSET offsetof(ngx_http_conf_ctx_t, srv_conf)
#define NGX_HTTP_LOC_CONF_OFFSET offsetof(ngx_http_conf_ctx_t, loc_conf)
//
#define ngx_http_get_module_main_conf(r, module) \
(r)->main_conf[module.ctx_index]
#define ngx_http_get_module_srv_conf(r, module) (r)->srv_conf[module.ctx_index]
#define ngx_http_get_module_loc_conf(r, module) (r)->loc_conf[module.ctx_index]
#define ngx_http_conf_get_module_main_conf(cf, module) \
((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]
#define ngx_http_conf_get_module_srv_conf(cf, module) \
((ngx_http_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index]
#define ngx_http_conf_get_module_loc_conf(cf, module) \
((ngx_http_conf_ctx_t *) cf->ctx)->loc_conf[module.ctx_index]
#define ngx_http_cycle_get_module_main_conf(cycle, module) \
(cycle->conf_ctx[ngx_http_module.index] ? \
((ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]) \
->main_conf[module.ctx_index]: \
NULL)
#define ngx_get_conf(conf_ctx, module) conf_ctx[module.index]
전형 적 인 설정 명령 몇 개 를 보 겠 습 니 다.
우선 env 입 니 다. DIRECT CONF 명령 입 니 다.
// create_conf
static ngx_core_module_t ngx_core_module_ctx = {
ngx_string("core"),
ngx_core_module_create_conf,
ngx_core_module_init_conf
};
................................
{ ngx_string("env"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_set_env,
0,
0,
NULL },
static char *
ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
//
ngx_core_conf_t *ccf = conf;
.............................
return NGX_CONF_OK;
}
그리고 http 의 루트 명령:
{ ngx_string("root"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
ngx_http_core_root,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
static char *
ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
// ( NGX_HTTP_LOC_CONF_OFFSET)
ngx_http_core_loc_conf_t *clcf = conf;
.......................................
return NGX_CONF_OK;
}
마지막 으로 왜 4 급 포인터 가 있 는 지 살 펴 보 겠 습 니 다. 이것 은 모듈 등급 과 관련 된 것 입 니 다. 1 급 모듈 만 있 으 면 2 급 포인터 만 있 으 면 됩 니 다. 하지만 아직 2 급 모듈 이 있 습 니 다. 각 1 급 모듈 의 2 급 포인터 안 에는 반드시 확장 포인터 가 있어 야 본 급 모듈 의 문맥 을 보존 해 야 합 니 다. 그러면 자 연 스 럽 게 4 급 포인터 입 니 다. 이벤트 모듈 을 자세히 볼 수 있 습 니 다.그 안 이 비교적 뚜렷 하 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.